forked from LiveCarta/LiveCartaWP
Changed source root directory
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
class Postsmtp_ContactForm7 {
|
||||
|
||||
private $result_error;
|
||||
|
||||
public function __construct() {
|
||||
add_action( 'wpcf7_mail_failed', array( $this, 'save_error' ) );
|
||||
add_filter( 'wpcf7_ajax_json_echo', array( $this, 'change_rest_response' ), 10, 2 );
|
||||
}
|
||||
|
||||
public function save_error($contact_form) {
|
||||
$this->result_error = apply_filters( 'postman_wp_mail_result', null );
|
||||
}
|
||||
|
||||
public function change_rest_response( $response ) {
|
||||
if ( array_key_exists('status', $response) && $response['status'] == 'mail_failed' ) {
|
||||
$message = $this->result_error ['exception']->getMessage();
|
||||
|
||||
if ( ! $message || $message == '' ) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$currentTransport = PostmanOptions::getInstance()->getTransportType();
|
||||
$result = json_decode($message);
|
||||
$is_json = (json_last_error() == JSON_ERROR_NONE);
|
||||
|
||||
switch ($currentTransport) {
|
||||
case 'gmail_api':
|
||||
$response['message'] = $is_json ? $result->error->message : $message;
|
||||
break;
|
||||
default:
|
||||
$response['message'] = $is_json ? json_encode(json_decode($message), JSON_PRETTY_PRINT) : $message;
|
||||
}
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
require_once 'PostmanModuleTransport.php';
|
||||
if (! class_exists ( 'PostmanSmtpModuleTransport' )) {
|
||||
class PostmanDefaultModuleTransport extends PostmanAbstractZendModuleTransport implements PostmanZendModuleTransport {
|
||||
const SLUG = 'default';
|
||||
private $fromName;
|
||||
private $fromEmail;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mixed $rootPluginFilenameAndPath
|
||||
*/
|
||||
public function __construct($rootPluginFilenameAndPath) {
|
||||
parent::__construct ( $rootPluginFilenameAndPath );
|
||||
$this->init ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Copied from WordPress core
|
||||
* Set the from name and email
|
||||
*/
|
||||
public function init() {
|
||||
parent::init();
|
||||
// From email and name
|
||||
// If we don't have a name from the input headers
|
||||
$this->fromName = apply_filters( 'wp_mail_from_name', 'WordPress' );
|
||||
|
||||
/*
|
||||
* If we don't have an email from the input headers default to wordpress@$sitename
|
||||
* Some hosts will block outgoing mail from this address if it doesn't exist but
|
||||
* there's no easy alternative. Defaulting to admin_email might appear to be another
|
||||
* option but some hosts may refuse to relay mail from an unknown domain. See
|
||||
* https://core.trac.wordpress.org/ticket/5007.
|
||||
*/
|
||||
|
||||
// Get the site domain and get rid of www.
|
||||
$site_url = get_bloginfo( 'url' );
|
||||
$sitename = strtolower ( PostmanUtils::getHost( $site_url ) );
|
||||
|
||||
$this->fromEmail = apply_filters( 'wp_mail_from', 'wordpress@' . $sitename );
|
||||
}
|
||||
public function isConfiguredAndReady() {
|
||||
return false;
|
||||
}
|
||||
public function isReadyToSendMail() {
|
||||
return true;
|
||||
}
|
||||
public function getFromEmailAddress() {
|
||||
return $this->fromEmail;
|
||||
}
|
||||
public function getFromName() {
|
||||
return $this->fromName;
|
||||
}
|
||||
public function getEnvelopeFromEmailAddress() {
|
||||
return $this->getFromEmailAddress ();
|
||||
}
|
||||
public function isEmailValidationSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanAbstractZendModuleTransport::validateTransportConfiguration()
|
||||
*/
|
||||
protected function validateTransportConfiguration() {
|
||||
return array ();
|
||||
// no-op, always valid
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanModuleTransport::createMailEngine()
|
||||
*/
|
||||
public function createMailEngine() {
|
||||
require_once 'PostmanZendMailEngine.php';
|
||||
return new PostmanZendMailEngine ( $this );
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanZendModuleTransport::createZendMailTransport()
|
||||
*/
|
||||
public function createZendMailTransport($fakeHostname, $fakeConfig) {
|
||||
$config = array (
|
||||
'port' => $this->getPort ()
|
||||
);
|
||||
return new Postman_Zend_Mail_Transport_Smtp ( $this->getHostname (), $config );
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether Mail Engine locking is needed
|
||||
*
|
||||
* @see PostmanModuleTransport::requiresLocking()
|
||||
*/
|
||||
public function isLockingRequired() {
|
||||
return PostmanOptions::AUTHENTICATION_TYPE_OAUTH2 == $this->getAuthenticationType ();
|
||||
}
|
||||
public function getSlug() {
|
||||
return self::SLUG;
|
||||
}
|
||||
public function getName() {
|
||||
return __ ( 'Default', 'post-smtp' );
|
||||
}
|
||||
public function getHostname() {
|
||||
return 'localhost';
|
||||
}
|
||||
public function getPort() {
|
||||
return 25;
|
||||
}
|
||||
public function getSecurityType() {
|
||||
return PostmanOptions::SECURITY_TYPE_NONE;
|
||||
}
|
||||
public function getAuthenticationType() {
|
||||
return PostmanOptions::AUTHENTICATION_TYPE_NONE;
|
||||
}
|
||||
public function getCredentialsId() {
|
||||
$options = PostmanOptions::getInstance ();
|
||||
if ($options->isAuthTypeOAuth2 ()) {
|
||||
return $options->getClientId ();
|
||||
} else {
|
||||
return $options->getUsername ();
|
||||
}
|
||||
}
|
||||
public function getCredentialsSecret() {
|
||||
$options = PostmanOptions::getInstance ();
|
||||
if ($options->isAuthTypeOAuth2 ()) {
|
||||
return $options->getClientSecret ();
|
||||
} else {
|
||||
return $options->getPassword ();
|
||||
}
|
||||
}
|
||||
public function isServiceProviderGoogle($hostname) {
|
||||
return PostmanUtils::endsWith ( $hostname, 'gmail.com' );
|
||||
}
|
||||
public function isServiceProviderMicrosoft($hostname) {
|
||||
return PostmanUtils::endsWith ( $hostname, 'live.com' );
|
||||
}
|
||||
public function isServiceProviderYahoo($hostname) {
|
||||
return strpos ( $hostname, 'yahoo' );
|
||||
}
|
||||
public function isOAuthUsed($authType) {
|
||||
return false;
|
||||
}
|
||||
public final function getConfigurationBid(PostmanWizardSocket $hostData, $userAuthOverride, $originalSmtpServer) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does not participate in the Wizard process;
|
||||
*
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanModuleTransport::getSocketsForSetupWizardToProbe()
|
||||
*/
|
||||
public function getSocketsForSetupWizardToProbe($hostname, $smtpServerGuess) {
|
||||
return array ();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true, to prevent from errors because it's default Module Transport.
|
||||
*
|
||||
* @since 2.1.4
|
||||
* @version 1.0
|
||||
*/
|
||||
public function has_granted() {
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
if( !class_exists( 'PostmanElasticEmailMailEngine' ) ):
|
||||
|
||||
require 'Services/ElasticEmail/Handler.php';
|
||||
|
||||
class PostmanElasticEmailMailEngine implements PostmanMailEngine {
|
||||
|
||||
protected $logger;
|
||||
|
||||
private $transcript;
|
||||
|
||||
private $api_key;
|
||||
|
||||
|
||||
/**
|
||||
* @since 2.6.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function __construct( $api_key ) {
|
||||
|
||||
assert( !empty( $api_key ) );
|
||||
$this->api_key = $api_key;
|
||||
|
||||
// create the logger
|
||||
$this->logger = new PostmanLogger( get_class( $this ) );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.6.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getTranscript() {
|
||||
|
||||
return $this->transcript;
|
||||
|
||||
}
|
||||
|
||||
private function addAttachmentsToMail( PostmanMessage $message ) {
|
||||
|
||||
$attachments = $message->getAttachments();
|
||||
if ( ! is_array( $attachments ) ) {
|
||||
// WordPress may a single filename or a newline-delimited string list of multiple filenames
|
||||
$attArray = explode( PHP_EOL, $attachments );
|
||||
} else {
|
||||
$attArray = $attachments;
|
||||
}
|
||||
// otherwise WordPress sends an array
|
||||
$attachments = array();
|
||||
foreach ( $attArray as $file ) {
|
||||
if ( ! empty( $file ) ) {
|
||||
$this->logger->debug( 'Adding attachment: ' . $file );
|
||||
|
||||
$file_name = basename( $file );
|
||||
$file_parts = explode( '.', $file_name );
|
||||
$file_type = wp_check_filetype( $file );
|
||||
$attachments[] = array(
|
||||
'BinaryContent' => base64_encode( file_get_contents( $file ) ),
|
||||
'Name' => $file_name,
|
||||
'ContentType' => $file_type['type']
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $attachments;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.6.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function send( PostmanMessage $message ) {
|
||||
|
||||
$options = PostmanOptions::getInstance();
|
||||
$email_content = array();
|
||||
|
||||
//ElasticEmail preparation
|
||||
if ( $this->logger->isDebug() ) {
|
||||
|
||||
$this->logger->debug( 'Creating SendGrid service with apiKey=' . $this->api_key );
|
||||
|
||||
}
|
||||
|
||||
$elasticemail = new PostmanElasticEmail( $this->api_key );
|
||||
|
||||
//$email_content['Recipients'] =
|
||||
|
||||
//Adding to receipients
|
||||
$to = array();
|
||||
foreach ( (array)$message->getToRecipients() as $key => $recipient ) {
|
||||
|
||||
$to[] = !empty( $recipient->getName() ) ? $recipient->getName() . ' <' . $recipient->getEmail() . '>' : $recipient->getEmail();
|
||||
|
||||
}
|
||||
|
||||
//Adding cc receipients
|
||||
$cc = array();
|
||||
foreach ( ( array ) $message->getCcRecipients() as $recipient ) {
|
||||
|
||||
$cc[] = !empty( $recipient->getName() ) ? $recipient->getName() . ' <' . $recipient->getEmail() . '>' : $recipient->getEmail();
|
||||
|
||||
}
|
||||
|
||||
//Adding bcc receipients
|
||||
$bcc = array();
|
||||
foreach ( ( array ) $message->getBccRecipients() as $recipient ) {
|
||||
|
||||
$bcc[] = !empty( $recipient->getName() ) ? $recipient->getName() . ' <' . $recipient->getEmail() . '>' : $recipient->getEmail();
|
||||
|
||||
}
|
||||
|
||||
$email_content['Recipients'] = array(
|
||||
'To' => $to,
|
||||
'CC' => $cc,
|
||||
'BCC' => $bcc
|
||||
);
|
||||
|
||||
//Adding PlainText Body
|
||||
if( !empty( $message->getBodyTextPart() ) ){
|
||||
|
||||
$body = $message->getBodyTextPart();
|
||||
$this->logger->debug( 'Adding body as text' );
|
||||
$email_content['Content'] = array(
|
||||
'Body' => array(
|
||||
0 => array(
|
||||
'ContentType' => 'PlainText',
|
||||
'Content' => $body
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
//Adding HTML Body
|
||||
if( !empty( $message->getBodyHtmlPart() ) ){
|
||||
|
||||
$body = $message->getBodyHtmlPart();
|
||||
$this->logger->debug( 'Adding body as html' );
|
||||
$email_content['Content'] = array(
|
||||
'Body' => array(
|
||||
0 => array(
|
||||
'ContentType' => 'HTML',
|
||||
'Content' => $body
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$sender = $message->getFromAddress();
|
||||
$senderEmail = !empty( $sender->getEmail() ) ? $sender->getEmail() : $options->getMessageSenderEmail();
|
||||
$senderName = !empty( $sender->getName() ) ? $sender->getName() : $options->getMessageSenderName();
|
||||
|
||||
$replyTo = $message->getReplyTo();
|
||||
$replyTo_email = !empty( $replyTo ) ? $replyTo->getEmail() : '';
|
||||
|
||||
|
||||
$email_content['Content']['EnvelopeFrom'] = !empty( $senderName ) ? $senderName . ' <' . $senderEmail . '>' : $senderEmail;
|
||||
$email_content['Content']['From'] = !empty( $senderName ) ? $senderName . ' <' . $senderEmail . '>' : $senderEmail;
|
||||
|
||||
if( !empty( $replyTo_email ) ) {
|
||||
|
||||
$email_content['Content']['ReplyTo'] = !empty( $replyTo->getName() ) ? $replyTo->getName() . ' <' . $replyTo->getEmail() . '>' : $replyTo->getEmail();
|
||||
|
||||
}
|
||||
|
||||
$email_content['Content']['Subject'] = $message->getSubject();
|
||||
|
||||
$attachments = $this->addAttachmentsToMail( $message );
|
||||
|
||||
if( !empty( $attachments ) ) {
|
||||
|
||||
$email_content['Content']['Attachments'] = $attachments;
|
||||
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
// send the message
|
||||
if ( $this->logger->isDebug() ) {
|
||||
$this->logger->debug( 'Sending mail' );
|
||||
}
|
||||
|
||||
$response = $elasticemail->send( $email_content );
|
||||
|
||||
$this->transcript = print_r( $response, true );
|
||||
$this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
|
||||
$this->transcript .= print_r( $email_content, true );
|
||||
$this->logger->debug( 'Transcript=' . $this->transcript );
|
||||
|
||||
} catch (Exception $e) {
|
||||
|
||||
$this->transcript = $e->getMessage();
|
||||
$this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
|
||||
$this->transcript .= print_r( $email_content, true );
|
||||
$this->logger->debug( 'Transcript=' . $this->transcript );
|
||||
|
||||
throw $e;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
endif;
|
||||
@@ -0,0 +1,321 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once 'PostmanModuleTransport.php';
|
||||
|
||||
/**
|
||||
* Postman ElasticEmail
|
||||
* @since 2.6.0
|
||||
* @version 1.0
|
||||
*/
|
||||
if( !class_exists( 'PostmanElasticEmailTransport' ) ):
|
||||
class PostmanElasticEmailTransport extends PostmanAbstractModuleTransport implements PostmanModuleTransport {
|
||||
|
||||
const SLUG = 'elasticemail_api';
|
||||
const PORT = 2525;
|
||||
const HOST = 'smtp.elasticemail.com';
|
||||
const PRIORITY = 51000;
|
||||
const ELASTICEMAIL_AUTH_OPTIONS = 'postman_elasticemail_auth_options';
|
||||
const ELASTICEMAIL_AUTH_SECTION = 'postman_elasticemail_auth_section';
|
||||
|
||||
/**
|
||||
* PostmanElasticEmailTransport constructor.
|
||||
* @param $rootPluginFilenameAndPath
|
||||
* @since 2.6.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function __construct( $rootPluginFilenameAndPath ) {
|
||||
|
||||
parent::__construct ( $rootPluginFilenameAndPath );
|
||||
|
||||
// add a hook on the plugins_loaded event
|
||||
add_action ( 'admin_init', array ( $this, 'on_admin_init' ) );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
* @since 2.6.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getPort() {
|
||||
return self::PORT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @since 2.6.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getSlug() {
|
||||
return self::SLUG;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @since 2.6.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getProtocol() {
|
||||
return 'https';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @since 2.6.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getHostname() {
|
||||
return self::HOST;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.6.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getConfigurationBid( PostmanWizardSocket $hostData, $userAuthOverride, $originalSmtpServer ) {
|
||||
|
||||
$recommendation = array();
|
||||
$recommendation ['priority'] = 0;
|
||||
$recommendation ['transport'] = self::SLUG;
|
||||
$recommendation ['hostname'] = null; // scribe looks this
|
||||
$recommendation ['label'] = $this->getName();
|
||||
$recommendation['logo_url'] = $this->getLogoURL();
|
||||
|
||||
if ($hostData->hostname == self::HOST && $hostData->port == self::PORT) {
|
||||
$recommendation ['priority'] = self::PRIORITY;
|
||||
/* translators: where variables are (1) transport name (2) host and (3) port */
|
||||
$recommendation ['message'] = sprintf ( __ ( ('Postman recommends the %1$s to host %2$s on port %3$d.') ), $this->getName(), self::HOST, self::PORT );
|
||||
}
|
||||
|
||||
return $recommendation;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.6.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function createMailEngine() {
|
||||
|
||||
$api_key = $this->options->getElasticEmailApiKey();
|
||||
require_once 'PostmanElasticEmailMailEngine.php';
|
||||
$engine = new PostmanElasticEmailMailEngine( $api_key );
|
||||
|
||||
return $engine;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.6.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getName() {
|
||||
|
||||
return __( 'Elastic Email', 'post-smtp' );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.6.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getDeliveryDetails() {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PostmanWizardSocket $socket
|
||||
* @param $winningRecommendation
|
||||
* @param $userSocketOverride
|
||||
* @param $userAuthOverride
|
||||
* @return array
|
||||
* @since 2.6.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function createOverrideMenu( PostmanWizardSocket $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride ) {
|
||||
|
||||
$overrideItem = parent::createOverrideMenu ( $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride );
|
||||
|
||||
// push the authentication options into the $overrideItem structure
|
||||
$overrideItem ['auth_items'] = array (
|
||||
array (
|
||||
'selected' => true,
|
||||
'name' => __ ( 'API Key', 'post-smtp' ),
|
||||
'value' => 'api_key'
|
||||
)
|
||||
);
|
||||
|
||||
return $overrideItem;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.6.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function on_admin_init() {
|
||||
|
||||
if( PostmanUtils::isAdmin() ) {
|
||||
|
||||
$this->addSettings();
|
||||
$this->registerStylesAndScripts();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.6.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function addSettings()
|
||||
{
|
||||
|
||||
add_settings_section(
|
||||
self::ELASTICEMAIL_AUTH_SECTION,
|
||||
__('Authentication', 'post-smtp'),
|
||||
array( $this, 'printElasticEmailAuthSectionInfo' ),
|
||||
self::ELASTICEMAIL_AUTH_OPTIONS
|
||||
);
|
||||
|
||||
add_settings_field(
|
||||
PostmanOptions::ELASTICEMAIL_API_KEY,
|
||||
__( 'API Key', 'post-smtp' ),
|
||||
array( $this, 'elasticemail_api_key_callback' ),
|
||||
self::ELASTICEMAIL_AUTH_OPTIONS,
|
||||
self::ELASTICEMAIL_AUTH_SECTION
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.6.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function printElasticEmailAuthSectionInfo() {
|
||||
|
||||
printf (
|
||||
'<p id="wizard_elasticemail_auth_help">%s</p>', sprintf ( __ ( 'Create an account at <a href="%1$s" target="_blank">%2$s</a> and enter <a href="%3$s" target="_blank">an API key</a> below.', 'post-smtp' ),
|
||||
'https://www.elasticemail.com/', 'elasticemail.com', 'https://app.elasticemail.com/marketing/settings/new/create-api' )
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.6.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function elasticemail_api_key_callback() {
|
||||
|
||||
printf ( '<input type="password" autocomplete="off" id="elasticemail_api_key" name="postman_options[elasticemail_api_key]" value="%s" size="60" class="required ps-input ps-w-75" placeholder="%s"/>', null !== $this->options->getElasticEmailApiKey() ? esc_attr ( PostmanUtils::obfuscatePassword ( $this->options->getElasticEmailApiKey() ) ) : '', __ ( 'Required', 'post-smtp' ) );
|
||||
print ' <input type="button" id="toggleElasticEmailApiKey" value="Show Password" class="button button-secondary" style="visibility:hidden" />';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.6.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function registerStylesAndScripts() {
|
||||
|
||||
$pluginData = apply_filters( 'postman_get_plugin_metadata', null );
|
||||
|
||||
wp_register_script (
|
||||
'postman-elasticemail',
|
||||
plugins_url ( 'Postman/Postman-Mail/postman-elasticemail.js', $this->rootPluginFilenameAndPath ),
|
||||
array (
|
||||
PostmanViewController::JQUERY_SCRIPT,
|
||||
'jquery_validation',
|
||||
PostmanViewController::POSTMAN_SCRIPT
|
||||
),
|
||||
$pluginData['version']
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.6.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function enqueueScript() {
|
||||
|
||||
wp_enqueue_script( 'postman-elasticemail' );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.6.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function printWizardAuthenticationStep() {
|
||||
print '<section class="wizard_elasticemail">';
|
||||
$this->printElasticEmailAuthSectionInfo();
|
||||
printf ( '<label for="api_key">%s</label>', __ ( 'API Key', 'post-smtp' ) );
|
||||
print '<br />';
|
||||
print $this->elasticemail_api_key_callback();
|
||||
print '</section>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Socket's logo
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getLogoURL() {
|
||||
|
||||
return POST_SMTP_ASSETS . "images/logos/elasticemail.png";
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true, to prevent from errors because it's default Module Transport.
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function has_granted() {
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanTransport::getMisconfigurationMessage()
|
||||
* @since 2.6.0
|
||||
* @version 1.0
|
||||
*/
|
||||
protected function validateTransportConfiguration() {
|
||||
$messages = parent::validateTransportConfiguration ();
|
||||
$apiKey = $this->options->getElasticEmailApiKey ();
|
||||
if (empty ( $apiKey )) {
|
||||
array_push ( $messages, __ ( 'API Key can not be empty', 'post-smtp' ) . '.' );
|
||||
$this->setNotConfiguredAndReady ();
|
||||
}
|
||||
if (! $this->isSenderConfigured ()) {
|
||||
array_push ( $messages, __ ( 'Message From Address can not be empty', 'post-smtp' ) . '.' );
|
||||
$this->setNotConfiguredAndReady ();
|
||||
}
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mixed $data
|
||||
* @since 2.6.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function prepareOptionsForExport($data) {
|
||||
$data = parent::prepareOptionsForExport ( $data );
|
||||
$data [PostmanOptions::ELASTICEMAIL_API_KEY] = PostmanOptions::getInstance ()->getElasticEmailApiKey ();
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
endif;
|
||||
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
if (! class_exists ( 'PostmanEmailAddress' )) {
|
||||
class PostmanEmailAddress {
|
||||
private $name;
|
||||
private $email;
|
||||
public function __construct($email, $name = null) {
|
||||
// Break $recipient into name and address parts if in the format "Foo <bar@baz.com>"
|
||||
if (preg_match ( '/(.*)<(.+)>/', $email, $matches )) {
|
||||
if (count ( $matches ) == 3) {
|
||||
$name = $matches [1];
|
||||
$email = $matches [2];
|
||||
}
|
||||
}
|
||||
$this->setEmail ( trim ( $email ) );
|
||||
|
||||
if( !empty( $name ) ) {
|
||||
|
||||
$this->setName ( trim ( $name ) );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
public static function copy(PostmanEmailAddress $orig) {
|
||||
return new PostmanEmailAddress ( $orig->getEmail (), $orig->getName () );
|
||||
}
|
||||
public function getName() {
|
||||
return $this->name;
|
||||
}
|
||||
public function getEmail() {
|
||||
return $this->email;
|
||||
}
|
||||
public function format() {
|
||||
$name = $this->getName ();
|
||||
if (! empty ( $name )) {
|
||||
return sprintf ( '%s <%s>', $this->getName (), $this->getEmail () );
|
||||
} else {
|
||||
return sprintf ( '%s', $this->getEmail () );
|
||||
}
|
||||
}
|
||||
public function setName($name) {
|
||||
$this->name = $name;
|
||||
}
|
||||
public function setEmail($email) {
|
||||
$this->email = $email;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Accept a String of addresses or an array and return an array
|
||||
*
|
||||
* @param mixed $recipientList
|
||||
* @param mixed $recipients
|
||||
*/
|
||||
public static function convertToArray($emails) {
|
||||
assert ( ! empty ( $emails ) );
|
||||
if (! is_array ( $emails )) {
|
||||
// http://tiku.io/questions/955963/splitting-comma-separated-email-addresses-in-a-string-with-commas-in-quotes-in-p
|
||||
$t = str_getcsv ( $emails, ",", "\"", "\\" );
|
||||
$emails = array ();
|
||||
foreach ( $t as $k => $v ) {
|
||||
if (strpos ( $v, ',' ) !== false) {
|
||||
$t [$k] = '"' . str_replace ( ' <', '" <', $v );
|
||||
}
|
||||
$tokenizedEmail = trim ( $t [$k] );
|
||||
array_push ( $emails, $tokenizedEmail );
|
||||
}
|
||||
}
|
||||
return $emails;
|
||||
}
|
||||
public function log(PostmanLogger $log, $desc) {
|
||||
$message = $desc . ' email=' . $this->getEmail ();
|
||||
if (! empty ( $this->name )) {
|
||||
$message .= ' name=' . $this->getName ();
|
||||
}
|
||||
$log->debug ( $message );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'PostmanEmailItMailEngine' ) ) {
|
||||
|
||||
require_once 'Services/Emailit/Handler.php';
|
||||
|
||||
/**
|
||||
* Sends mail with the EmailIt API.
|
||||
*/
|
||||
class PostmanEmailItMailEngine implements PostmanMailEngine {
|
||||
|
||||
protected $logger;
|
||||
private $transcript;
|
||||
private $apiKey;
|
||||
|
||||
public function __construct( $apiKey ) {
|
||||
assert( ! empty( $apiKey ) );
|
||||
$this->apiKey = $apiKey;
|
||||
$this->logger = new PostmanLogger( get_class( $this ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an email via Emailit, including attachments if provided.
|
||||
*
|
||||
* @param PostmanMessage $message The message object.
|
||||
* @return void
|
||||
* @throws Exception On error.
|
||||
*/
|
||||
public function send( PostmanMessage $message ) {
|
||||
$options = PostmanOptions::getInstance();
|
||||
$emailit = new PostmanEmailIt( $this->apiKey );
|
||||
|
||||
$recipients = [];
|
||||
$duplicates = [];
|
||||
|
||||
// Sender.
|
||||
$sender = $message->getFromAddress();
|
||||
$senderEmail = ! empty( $sender->getEmail() ) ? $sender->getEmail() : $options->getMessageSenderEmail();
|
||||
$senderName = ! empty( $sender->getName() ) ? $sender->getName() : $options->getMessageSenderName();
|
||||
$sender->log( $this->logger, 'From' );
|
||||
|
||||
// Recipients.
|
||||
foreach ( (array) $message->getToRecipients() as $recipient ) {
|
||||
if ( ! in_array( $recipient->getEmail(), $duplicates ) ) {
|
||||
$recipients[] = $recipient->getEmail();
|
||||
$duplicates[] = $recipient->getEmail();
|
||||
}
|
||||
}
|
||||
|
||||
// Subject and Body.
|
||||
$subject = $message->getSubject();
|
||||
$textPart = $message->getBodyTextPart();
|
||||
$htmlPart = $message->getBodyHtmlPart();
|
||||
$htmlContent = ! empty( $htmlPart ) ? $htmlPart : nl2br( $textPart );
|
||||
|
||||
if ( empty( $htmlContent ) ) {
|
||||
$htmlContent = '<p>(No content)</p>';
|
||||
}
|
||||
|
||||
$from = $senderEmail;
|
||||
if ( ! empty( $senderName ) ) {
|
||||
$from = sprintf( '%s <%s>', $senderName, $senderEmail );
|
||||
}
|
||||
|
||||
$content = [
|
||||
'from' => $from,
|
||||
'to' => implode( ',', $recipients ),
|
||||
'subject' => $subject,
|
||||
'html' => $htmlContent,
|
||||
'text' => wp_strip_all_tags( $textPart ?: $htmlPart ),
|
||||
];
|
||||
|
||||
// Attachments.
|
||||
$attachments = $this->addAttachmentsToMail( $message );
|
||||
if ( ! empty( $attachments ) ) {
|
||||
$content['attachments'] = $attachments;
|
||||
}
|
||||
|
||||
// Send.
|
||||
try {
|
||||
$this->logger->debug( 'Sending mail via EmailIt' );
|
||||
$response = $emailit->send( $content );
|
||||
$responseCode = wp_remote_retrieve_response_code( $response );
|
||||
$responseBody = wp_remote_retrieve_body( $response );
|
||||
|
||||
if ( $responseCode === 200 || $responseCode === 202 ) {
|
||||
$this->transcript = 'Email sent successfully.' . PHP_EOL;
|
||||
$this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS . PHP_EOL;
|
||||
$this->transcript .= print_r( $content, true );
|
||||
$this->logger->debug( 'Transcript=' . $this->transcript );
|
||||
} else {
|
||||
$decodedBody = json_decode( $responseBody, true );
|
||||
$errorMessage = $this->extractErrorMessage( $decodedBody, $responseCode );
|
||||
throw new Exception( $errorMessage );
|
||||
}
|
||||
} catch ( Exception $e ) {
|
||||
$this->transcript = $e->getMessage() . PHP_EOL;
|
||||
$this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS . PHP_EOL;
|
||||
$this->transcript .= print_r( $content, true );
|
||||
$this->logger->debug( 'Transcript=' . $this->transcript );
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares attachments for the API.
|
||||
*
|
||||
* @param PostmanMessage $message The message object.
|
||||
* @return array
|
||||
*/
|
||||
private function addAttachmentsToMail( PostmanMessage $message ) {
|
||||
$attachments = $message->getAttachments();
|
||||
$attArray = is_array( $attachments ) ? $attachments : explode( PHP_EOL, $attachments );
|
||||
$result = [];
|
||||
|
||||
foreach ( $attArray as $file ) {
|
||||
if ( ! empty( $file ) ) {
|
||||
$this->logger->debug( 'Adding attachment: ' . $file );
|
||||
$fileName = basename( $file );
|
||||
$fileType = wp_check_filetype( $file );
|
||||
$result[] = [
|
||||
'content' => base64_encode( file_get_contents( $file ) ),
|
||||
'type' => $fileType['type'],
|
||||
'filename' => $fileName,
|
||||
'disposition' => 'attachment',
|
||||
'name' => pathinfo( $fileName, PATHINFO_FILENAME ),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return debug transcript.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTranscript() {
|
||||
return $this->transcript;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the error message from a JSON-decoded response.
|
||||
*
|
||||
* @param array $decodedBody The response body.
|
||||
* @param int $responseCode HTTP code.
|
||||
* @return string
|
||||
*/
|
||||
private function extractErrorMessage( $decodedBody, $responseCode ) {
|
||||
if ( is_array( $decodedBody ) ) {
|
||||
if ( isset( $decodedBody['message'] ) && is_string( $decodedBody['message'] ) ) {
|
||||
return $decodedBody['message'];
|
||||
}
|
||||
if ( isset( $decodedBody['error'] ) ) {
|
||||
return is_string( $decodedBody['error'] )
|
||||
? $decodedBody['error']
|
||||
: ( $decodedBody['error']['message'] ?? $this->getErrorMessageFromCode( $responseCode ) );
|
||||
}
|
||||
}
|
||||
|
||||
return $this->getErrorMessageFromCode( $responseCode );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a user-friendly error message based on HTTP response code.
|
||||
*
|
||||
* @param int $response_code HTTP status code returned by the EmailIt API.
|
||||
* @return string Translated error message.
|
||||
*/
|
||||
private function getErrorMessageFromCode( $response_code ) {
|
||||
switch ( $response_code ) {
|
||||
case 400:
|
||||
return __( 'Bad request. Please check your email data.', 'suremails' );
|
||||
case 401:
|
||||
return __( 'Unauthorized. Please check your API key.', 'suremails' );
|
||||
case 403:
|
||||
return __( 'Forbidden. Access denied.', 'suremails' );
|
||||
case 404:
|
||||
return __( 'Not found. Please check the API endpoint.', 'suremails' );
|
||||
case 422:
|
||||
return __( 'Domain verification required. Your sending domain must be verified in Emailit before you can send emails. Please verify your domain in your Emailit dashboard at https://app.emailit.com/domains', 'suremails' );
|
||||
case 429:
|
||||
return __( 'Rate limit exceeded. Please try again later.', 'suremails' );
|
||||
case 500:
|
||||
return __( 'Internal server error. Please try again later.', 'suremails' );
|
||||
default:
|
||||
// translators: %d is the HTTP error code.
|
||||
return sprintf( __( 'HTTP error %d occurred.', 'suremails' ), $response_code );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
require_once 'PostmanModuleTransport.php';
|
||||
|
||||
/**
|
||||
* Postman Emailit Transport
|
||||
*
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
if( !class_exists( 'PostmanEmailitTransport' ) ):
|
||||
class PostmanEmailitTransport extends PostmanAbstractModuleTransport implements PostmanModuleTransport {
|
||||
const SLUG = 'emailit_api';
|
||||
const PORT = 443;
|
||||
const HOST = 'api.emailit.com'; // Change to actual Emailit API host if different
|
||||
const PRIORITY = 48010;
|
||||
const EMAILIT_AUTH_OPTIONS = 'postman_emailit_auth_options';
|
||||
const EMAILIT_AUTH_SECTION = 'postman_emailit_auth_section';
|
||||
|
||||
/**
|
||||
* PostmanEmailitTransport constructor.
|
||||
* @param $rootPluginFilenameAndPath
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function __construct($rootPluginFilenameAndPath) {
|
||||
parent::__construct($rootPluginFilenameAndPath);
|
||||
add_action('admin_init', array($this, 'on_admin_init'));
|
||||
}
|
||||
public function getProtocol() {
|
||||
return 'https';
|
||||
}
|
||||
|
||||
// this should be standard across all transports
|
||||
public function getSlug() {
|
||||
return self::SLUG;
|
||||
}
|
||||
|
||||
public function getName() {
|
||||
return __('Emailit API', 'post-smtp');
|
||||
}
|
||||
|
||||
/**
|
||||
* v0.2.1
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getHostname() {
|
||||
return self::HOST;
|
||||
}
|
||||
|
||||
/**
|
||||
* v0.2.1
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getPort() {
|
||||
return self::PORT;
|
||||
}
|
||||
|
||||
/**
|
||||
* v1.7.0
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTransportType() {
|
||||
return 'Emailit_api';
|
||||
}
|
||||
/**
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function createMailEngine() {
|
||||
$apiKey = $this->options->getEmailitApiKey();
|
||||
require_once 'PostmanEmailitMailEngine.php';
|
||||
$engine = new PostmanEmailitMailEngine($apiKey);
|
||||
return $engine;
|
||||
}
|
||||
/**
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getDeliveryDetails() {
|
||||
/* translators: where (1) is the secure icon and (2) is the transport name */
|
||||
return sprintf(__('Postman will send mail via the <b>%1$s %2$s</b>.', 'post-smtp'), '🔐', $this->getName());
|
||||
}
|
||||
protected function validateTransportConfiguration() {
|
||||
$messages = parent::validateTransportConfiguration();
|
||||
$apiKey = $this->options->getEmailitApiKey();
|
||||
if (empty($apiKey)) {
|
||||
array_push($messages, __('API Key can not be empty', 'post-smtp') . '.');
|
||||
$this->setNotConfiguredAndReady();
|
||||
}
|
||||
if (!$this->isSenderConfigured()) {
|
||||
array_push($messages, __('Message From Address can not be empty', 'post-smtp') . '.');
|
||||
$this->setNotConfiguredAndReady();
|
||||
}
|
||||
return $messages;
|
||||
}
|
||||
/**
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getConfigurationBid(PostmanWizardSocket $hostData, $userAuthOverride, $originalSmtpServer) {
|
||||
$recommendation = array();
|
||||
$recommendation['priority'] = 0;
|
||||
$recommendation['transport'] = self::SLUG;
|
||||
$recommendation['hostname'] = null; // scribe looks this
|
||||
$recommendation['label'] = $this->getName();
|
||||
$recommendation['logo_url'] = $this->getLogoURL();
|
||||
if ($hostData->hostname == self::HOST && $hostData->port == self::PORT) {
|
||||
$recommendation['priority'] = self::PRIORITY;
|
||||
/* translators: where variables are (1) transport name (2) host and (3) port */
|
||||
$recommendation['message'] = sprintf(__('Postman recommends the %1$s to host %2$s on port %3$d.'), $this->getName(), self::HOST, self::PORT);
|
||||
}
|
||||
return $recommendation;
|
||||
}
|
||||
/**
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function on_admin_init() {
|
||||
if (PostmanUtils::isAdmin()) {
|
||||
$this->addSettings();
|
||||
$this->registerStylesAndScripts();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function addSettings() {
|
||||
add_settings_section( self::EMAILIT_AUTH_SECTION, __('Authentication', 'post-smtp'), array($this, 'printEmailitAuthSectionInfo'), self::EMAILIT_AUTH_OPTIONS );
|
||||
add_settings_field( 'emailit_api_key', __('API Key', 'post-smtp'), array($this, 'emailit_api_key_callback'), self::EMAILIT_AUTH_OPTIONS, self::EMAILIT_AUTH_SECTION );
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function printEmailitAuthSectionInfo() {
|
||||
printf(
|
||||
'<p id="wizard_emailit_auth_help">%s</p>',
|
||||
sprintf(
|
||||
__(
|
||||
'Create an account at <a href="%1$s" target="_blank">%2$s</a> and enter <a href="%3$s" target="_blank">your API key</a> and endpoint below.',
|
||||
'post-smtp'
|
||||
),
|
||||
'https://emailit.com/', 'emailit.com', 'https://emailit.com/'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function emailit_api_key_callback() {
|
||||
printf('<input type="password" autocomplete="off" id="emailit_api_key" name="postman_options[emailit_api_key]" value="%s" size="60" class="required ps-input ps-w-75" placeholder="%s"/>', null !== $this->options->getEmailitApiKey() ? esc_attr(PostmanUtils::obfuscatePassword($this->options->getEmailitApiKey())) : '', __('Required', 'post-smtp'));
|
||||
print ' <input type="button" id="toggleEmailitApiKey" value="Show Password" class="button button-secondary" style="visibility:hidden" />';
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function registerStylesAndScripts() {
|
||||
|
||||
// register the stylesheet and javascript external resources
|
||||
$pluginData = apply_filters ( 'postman_get_plugin_metadata', null );
|
||||
wp_register_script (
|
||||
'postman-emailit',
|
||||
plugins_url ( 'Postman/Postman-Mail/postman-emailit.js', $this->rootPluginFilenameAndPath ),
|
||||
array (
|
||||
PostmanViewController::JQUERY_SCRIPT,
|
||||
'jquery_validation',
|
||||
PostmanViewController::POSTMAN_SCRIPT
|
||||
),
|
||||
$pluginData['version']
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function enqueueScript() {
|
||||
|
||||
wp_enqueue_script( 'postman-emailit' );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function printWizardAuthenticationStep() {
|
||||
print '<section class="wizard_emailit">';
|
||||
$this->printEmailitAuthSectionInfo();
|
||||
printf('<label for="api_key">%s</label>', __('API Key', 'post-smtp'));
|
||||
print '<br />';
|
||||
$this->emailit_api_key_callback();
|
||||
print '</section>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Socket's logo
|
||||
*
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getLogoURL() {
|
||||
return POST_SMTP_ASSETS . "images/logos/emailit.png";
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function has_granted() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
endif;
|
||||
@@ -0,0 +1,351 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
use \PostSMTP\Vendor\Google_Client;
|
||||
use \PostSMTP\Vendor\Google\Service\Gmail;
|
||||
|
||||
require_once 'PostmanModuleTransport.php';
|
||||
|
||||
/**
|
||||
* This class integrates Postman with the Gmail API
|
||||
* http://ctrlq.org/code/19860-gmail-api-send-emails
|
||||
*
|
||||
* @author jasonhendriks
|
||||
*
|
||||
*/
|
||||
class PostmanGmailApiModuleTransport extends PostmanAbstractZendModuleTransport implements PostmanZendModuleTransport {
|
||||
const SLUG = 'gmail_api';
|
||||
const PORT = 443;
|
||||
const HOST = 'www.googleapis.com';
|
||||
const ENCRYPTION_TYPE = 'ssl';
|
||||
const PRIORITY = 49000;
|
||||
private $gmail_oneclick_enabled = false;
|
||||
public function __construct($rootPluginFilenameAndPath) {
|
||||
parent::__construct ( $rootPluginFilenameAndPath );
|
||||
$this->gmail_oneclick_enabled = in_array( 'gmail-oneclick', get_option( 'post_smtp_pro', [] )['extensions'] ?? [] );
|
||||
|
||||
// add a hook on the plugins_loaded event
|
||||
add_action ( 'admin_init', array (
|
||||
$this,
|
||||
'on_admin_init'
|
||||
) );
|
||||
}
|
||||
public function getProtocol() {
|
||||
return 'https';
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanAbstractModuleTransport::isServiceProviderGoogle()
|
||||
*/
|
||||
public function isServiceProviderGoogle($hostname) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanModuleTransport::createMailEngine()
|
||||
*/
|
||||
public function createMailEngine() {
|
||||
require_once 'PostmanZendMailEngine.php';
|
||||
return new PostmanZendMailEngine ( $this );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanZendModuleTransport::createZendMailTransport()
|
||||
*/
|
||||
public function createZendMailTransport($fakeHostname, $fakeConfig) {
|
||||
if (PostmanOptions::AUTHENTICATION_TYPE_OAUTH2 == $this->getAuthenticationType ()) {
|
||||
$config = PostmanOAuth2ConfigurationFactory::createConfig ( $this );
|
||||
} else {
|
||||
$config = PostmanBasicAuthConfigurationFactory::createConfig ( $this );
|
||||
}
|
||||
|
||||
// Google's autoloader will try and load this so we list it first
|
||||
require_once 'PostmanGmailApiModuleZendMailTransport.php';
|
||||
|
||||
//Load Google Client API
|
||||
require_once 'libs/vendor/autoload.php';
|
||||
|
||||
// build the Gmail Client
|
||||
$authToken = PostmanOAuthToken::getInstance ();
|
||||
$client = new Google_Client(
|
||||
array(
|
||||
'client_id' => $this->options->getClientId(),
|
||||
'client_secret' => $this->options->getClientSecret(),
|
||||
'redirect_uris' => array(
|
||||
$this->getScribe()->getCallbackUrl(),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
// rebuild the google access token
|
||||
$token = new stdClass ();
|
||||
$client->setApplicationName( 'Post SMTP ' . POST_SMTP_VER );
|
||||
$client->setAccessType( 'offline' );
|
||||
$client->setApprovalPrompt( 'force' );
|
||||
$client->setIncludeGrantedScopes( true );
|
||||
$client->setScopes( array( Gmail::MAIL_GOOGLE_COM ) );
|
||||
$client->setRedirectUri( $this->getScribe()->getCallbackUrl() );
|
||||
|
||||
if ( $this->gmail_oneclick_enabled ) {
|
||||
$config = [];
|
||||
return new PostmanGmailApiModuleZendMailTransport ( self::HOST, $config );
|
||||
}
|
||||
try {
|
||||
|
||||
//If Access Token Expired, get new one
|
||||
if( $client->isAccessTokenExpired() ) {
|
||||
$client->fetchAccessTokenWithRefreshToken( $authToken->getRefreshToken() );
|
||||
|
||||
}
|
||||
//Lets go with the old one
|
||||
else {
|
||||
$client->setAccessToken( $authToken->getAccessToken() );
|
||||
$client->setRefreshToken( $authToken->getRefreshToken() );
|
||||
|
||||
}
|
||||
|
||||
|
||||
} catch( Exception $e ) {
|
||||
|
||||
print_r( $e );
|
||||
die;
|
||||
|
||||
}
|
||||
|
||||
$token->access_token = $client->getAccessToken();
|
||||
$token->refresh_token = $client->getRefreshToken();
|
||||
$token->token_type = 'Bearer';
|
||||
$token->expires_in = 3600;
|
||||
$token->id_token = null;
|
||||
$token->created = 0;
|
||||
$service = new Gmail( $client );
|
||||
|
||||
$config [PostmanGmailApiModuleZendMailTransport::SERVICE_OPTION] = $service;
|
||||
|
||||
return new PostmanGmailApiModuleZendMailTransport ( self::HOST, $config );
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether Mail Engine locking is needed
|
||||
*
|
||||
* @see PostmanModuleTransport::requiresLocking()
|
||||
*/
|
||||
public function isLockingRequired() {
|
||||
return PostmanOptions::AUTHENTICATION_TYPE_OAUTH2 == $this->getAuthenticationType ();
|
||||
}
|
||||
public function getSlug() {
|
||||
return self::SLUG;
|
||||
}
|
||||
public function getName() {
|
||||
return __ ( 'Gmail API', 'post-smtp' );
|
||||
}
|
||||
public function isEnvelopeFromValidationSupported() {
|
||||
return false;
|
||||
}
|
||||
public function getHostname() {
|
||||
return self::HOST;
|
||||
}
|
||||
public function getPort() {
|
||||
return self::PORT;
|
||||
}
|
||||
public function getAuthenticationType() {
|
||||
return $this->options->getAuthenticationType ();
|
||||
}
|
||||
public function getSecurityType() {
|
||||
return null;
|
||||
}
|
||||
public function getCredentialsId() {
|
||||
$this->options = $this->options;
|
||||
if ($this->options->isAuthTypeOAuth2 ()) {
|
||||
return $this->options->getClientId ();
|
||||
} else {
|
||||
return $this->options->getUsername ();
|
||||
}
|
||||
}
|
||||
public function getCredentialsSecret() {
|
||||
$this->options = $this->options;
|
||||
if ($this->options->isAuthTypeOAuth2 ()) {
|
||||
return $this->options->getClientSecret ();
|
||||
} else {
|
||||
return $this->options->getPassword ();
|
||||
}
|
||||
}
|
||||
public function isServiceProviderMicrosoft($hostname) {
|
||||
return false;
|
||||
}
|
||||
public function isServiceProviderYahoo($hostname) {
|
||||
return false;
|
||||
}
|
||||
public function isOAuthUsed($authType) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanAbstractModuleTransport::getDeliveryDetails()
|
||||
*/
|
||||
public function getDeliveryDetails() {
|
||||
/* translators: where (1) is the secure icon and (2) is the transport name */
|
||||
return sprintf ( __ ( 'Postman will send mail via the <b>%1$s %2$s</b>.', 'post-smtp' ), '🔐', $this->getName () );
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanAbstractZendModuleTransport::validateTransportConfiguration()
|
||||
*/
|
||||
protected function validateTransportConfiguration() {
|
||||
$messages = parent::validateTransportConfiguration ();
|
||||
if (empty ( $messages )) {
|
||||
$this->setReadyForOAuthGrant ();
|
||||
if ($this->isPermissionNeeded ()) {
|
||||
/* translators: %1$s is the Client ID label, and %2$s is the Client Secret label */
|
||||
$message = sprintf ( __ ( 'You have configured OAuth 2.0 authentication, but have not received permission to use it.', 'post-smtp' ), $this->getScribe ()->getClientIdLabel (), $this->getScribe ()->getClientSecretLabel () );
|
||||
$message .= sprintf ( ' <a href="%s">%s</a>.', PostmanUtils::getGrantOAuthPermissionUrl (), $this->getScribe ()->getRequestPermissionLinkText () );
|
||||
array_push ( $messages, $message );
|
||||
$this->setNotConfiguredAndReady ();
|
||||
}
|
||||
}
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a hostname, what ports should we test?
|
||||
*
|
||||
* May return an array of several combinations.
|
||||
*/
|
||||
public function getSocketsForSetupWizardToProbe($hostname, $smtpServerGuess) {
|
||||
$hosts = array ();
|
||||
if ($smtpServerGuess == null || PostmanUtils::isGoogle ( $smtpServerGuess )) {
|
||||
array_push ( $hosts, parent::createSocketDefinition ( $this->getHostname (), $this->getPort () ) );
|
||||
}
|
||||
return $hosts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Postman Gmail API supports delivering mail with these parameters:
|
||||
*
|
||||
* 70 gmail api on port 465 to www.googleapis.com
|
||||
*
|
||||
* @param mixed $hostData
|
||||
*/
|
||||
public function getConfigurationBid(PostmanWizardSocket $hostData, $userAuthOverride, $originalSmtpServer) {
|
||||
$recommendation = array ();
|
||||
$recommendation ['priority'] = 0;
|
||||
$recommendation ['transport'] = self::SLUG;
|
||||
$recommendation ['enc'] = PostmanOptions::SECURITY_TYPE_NONE;
|
||||
$recommendation ['auth'] = PostmanOptions::AUTHENTICATION_TYPE_OAUTH2;
|
||||
$recommendation ['hostname'] = null; // scribe looks this
|
||||
$recommendation ['label'] = $this->getName ();
|
||||
$recommendation ['display_auth'] = 'oauth2';
|
||||
$recommendation['logo_url'] = $this->getLogoURL();
|
||||
|
||||
if ($hostData->hostname == self::HOST && $hostData->port == self::PORT) {
|
||||
/* translators: where variables are (1) transport name (2) host and (3) port */
|
||||
$recommendation ['message'] = sprintf ( __ ( ('Postman recommends the %1$s to host %2$s on port %3$d.') ), $this->getName (), self::HOST, self::PORT );
|
||||
$recommendation ['priority'] = self::PRIORITY;
|
||||
}
|
||||
|
||||
return $recommendation;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function createOverrideMenu(PostmanWizardSocket $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride) {
|
||||
$overrideItem = parent::createOverrideMenu ( $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride );
|
||||
// push the authentication options into the $overrideItem structure
|
||||
$overrideItem ['auth_items'] = array (
|
||||
array (
|
||||
'selected' => true,
|
||||
'name' => __ ( 'OAuth 2.0 (requires Client ID and Client Secret)', 'post-smtp' ),
|
||||
'value' => 'oauth2'
|
||||
)
|
||||
);
|
||||
return $overrideItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 ();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function registerStylesAndScripts() {
|
||||
// register the stylesheet and javascript external resources
|
||||
$pluginData = apply_filters ( 'postman_get_plugin_metadata', null );
|
||||
wp_register_script ( 'postman_gmail_script', plugins_url ( 'Postman/Postman-Mail/postman_gmail.js', $this->rootPluginFilenameAndPath ), array (
|
||||
PostmanViewController::JQUERY_SCRIPT,
|
||||
'jquery_validation',
|
||||
PostmanViewController::POSTMAN_SCRIPT
|
||||
), $pluginData ['version'] );
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function enqueueScript() {
|
||||
wp_enqueue_script ( 'postman_gmail_script' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Socket's logo
|
||||
*
|
||||
* @since 2.1
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getLogoURL() {
|
||||
|
||||
return POST_SMTP_ASSETS . "images/logos/gmail.png";
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks is granted or not
|
||||
*
|
||||
* @since 2.1.4
|
||||
* @version 1.0
|
||||
*/
|
||||
public function has_granted() {
|
||||
|
||||
if( $this->isPermissionNeeded() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the HTML of not granted
|
||||
*
|
||||
* @since 2.1.4
|
||||
* @version 1.0
|
||||
*/
|
||||
public function get_not_granted_notice() {
|
||||
|
||||
return array(
|
||||
'message' => __( ' You are just a step away to get started', 'post-smtp' ),
|
||||
'url_text' => $this->getScribe()->getRequestPermissionLinkText(),
|
||||
'url' => PostmanUtils::getGrantOAuthPermissionUrl()
|
||||
);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,338 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
use \PostSMTP\Vendor\Google\Service\Gmail\Message;
|
||||
use \PostSMTP\Vendor\Google\Http\MediaFileUpload;
|
||||
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Transport
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @see Postman_Zend_Mime
|
||||
*/
|
||||
// require_once 'Zend/Mime.php';
|
||||
|
||||
/**
|
||||
*
|
||||
* @see Postman_Zend_Mail_Protocol_Smtp
|
||||
*/
|
||||
// require_once 'Zend/Mail/Protocol/Smtp.php';
|
||||
|
||||
/**
|
||||
*
|
||||
* @see Postman_Zend_Mail_Transport_Abstract
|
||||
*/
|
||||
// require_once 'Zend/Mail/Transport/Abstract.php';
|
||||
|
||||
/**
|
||||
* SMTP connection object
|
||||
*
|
||||
* Loads an instance of Postman_Zend_Mail_Protocol_Smtp and forwards smtp transactions
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Transport
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
if (! class_exists ( 'PostmanGmailApiModuleZendMailTransport' )) {
|
||||
class PostmanGmailApiModuleZendMailTransport extends Postman_Zend_Mail_Transport_Abstract {
|
||||
const SERVICE_OPTION = 'service';
|
||||
const MESSAGE_SENDER_EMAIL_OPTION = 'sender_email';
|
||||
private $logger;
|
||||
private $message;
|
||||
private $transcript;
|
||||
private $api_base_url;
|
||||
private $gmail_oneclick_enabled;
|
||||
|
||||
/**
|
||||
* EOL character string used by transport
|
||||
*
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
public $EOL = "\n";
|
||||
|
||||
/**
|
||||
* Remote smtp hostname or i.p.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_host;
|
||||
|
||||
/**
|
||||
* Port number
|
||||
*
|
||||
* @var integer|null
|
||||
*/
|
||||
protected $_port;
|
||||
|
||||
/**
|
||||
* Local client hostname or i.p.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_name = 'localhost';
|
||||
|
||||
/**
|
||||
* Authentication type OPTIONAL
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_auth;
|
||||
|
||||
/**
|
||||
* Config options for authentication
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_config;
|
||||
|
||||
/**
|
||||
* Instance of Postman_Zend_Mail_Protocol_Smtp
|
||||
*
|
||||
* @var Postman_Zend_Mail_Protocol_Smtp
|
||||
*/
|
||||
protected $_connection;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $host
|
||||
* OPTIONAL (Default: 127.0.0.1)
|
||||
* @param array $config
|
||||
* OPTIONAL (Default: null)
|
||||
* @return void
|
||||
*
|
||||
* @todo Someone please make this compatible
|
||||
* with the SendMail transport class.
|
||||
*/
|
||||
public function __construct($host = '127.0.0.1', Array $config = array()) {
|
||||
if (isset ( $config ['name'] )) {
|
||||
$this->_name = $config ['name'];
|
||||
}
|
||||
if (isset ( $config ['port'] )) {
|
||||
$this->_port = $config ['port'];
|
||||
}
|
||||
if (isset ( $config ['auth'] )) {
|
||||
$this->_auth = $config ['auth'];
|
||||
}
|
||||
|
||||
$this->_host = $host;
|
||||
$this->_config = $config;
|
||||
$this->logger = new PostmanLogger ( get_class ( $this ) );
|
||||
// Define API base URL for middleware.
|
||||
$this->api_base_url = 'https://connect.postmansmtp.com/wp-json/gmail-oauth/v1/send-email';
|
||||
// Check if Gmail One Click is enabled.
|
||||
$this->gmail_oneclick_enabled = in_array(
|
||||
'gmail-oneclick',
|
||||
isset( get_option( 'post_smtp_pro', array() )['extensions'] )
|
||||
? get_option( 'post_smtp_pro', array() )['extensions']
|
||||
: array(),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Class destructor to ensure all open connections are closed
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __destruct() {
|
||||
if ($this->_connection instanceof Postman_Zend_Mail_Protocol_Smtp) {
|
||||
try {
|
||||
$this->_connection->quit ();
|
||||
} catch ( Postman_Zend_Mail_Protocol_Exception $e ) {
|
||||
// ignore
|
||||
}
|
||||
$this->_connection->disconnect ();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the connection protocol instance
|
||||
*
|
||||
* @param Postman_Zend_Mail_Protocol_Abstract $client
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setConnection(Postman_Zend_Mail_Protocol_Abstract $connection) {
|
||||
$this->_connection = $connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the connection protocol instance
|
||||
*
|
||||
* @return Postman_Zend_Mail_Protocol_Abstract|null
|
||||
*/
|
||||
public function getConnection() {
|
||||
return $this->_connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an email via the Gmail API
|
||||
*
|
||||
* Uses URI https://www.googleapis.com
|
||||
*
|
||||
*
|
||||
* @return void
|
||||
* @todo Rename this to sendMail, it's a public method...
|
||||
*/
|
||||
public function _sendMail() {
|
||||
|
||||
// Prepare the message in message/rfc822
|
||||
$message = $this->header . Postman_Zend_Mime::LINEEND . $this->body;
|
||||
$this->message = $message;
|
||||
// The message needs to be encoded in Base64URL
|
||||
$encodedMessage = rtrim ( strtr ( base64_encode ( $message ), '+/', '-_' ), '=' );
|
||||
|
||||
|
||||
$file_size = strlen($message);
|
||||
|
||||
$result = array ();
|
||||
try {
|
||||
if ( $this->gmail_oneclick_enabled ) {
|
||||
// Prepare payload.
|
||||
$payload = array(
|
||||
'message' => $encodedMessage,
|
||||
'headers' => $this->header,
|
||||
'site_url' => get_site_url(),
|
||||
);
|
||||
|
||||
$response = wp_remote_post(
|
||||
$this->api_base_url,
|
||||
array(
|
||||
'method' => 'POST',
|
||||
'body' => wp_json_encode( $payload ),
|
||||
'headers' => array(
|
||||
'Content-Type' => 'application/json',
|
||||
),
|
||||
'timeout' => 30,
|
||||
)
|
||||
);
|
||||
|
||||
$body = wp_remote_retrieve_body( $response );
|
||||
$result_output = json_decode( $body, true );
|
||||
$result = isset( $result_output['data'] ) ? $result_output['data'] : array();
|
||||
|
||||
// ✅ Check for HTTP errors.
|
||||
if ( is_wp_error( $response ) ) {
|
||||
throw new Exception( 'Error in PostSMTP GMAIL API Request: ' . $response->get_error_message() );
|
||||
}
|
||||
|
||||
$response_code = wp_remote_retrieve_response_code( $response );
|
||||
$body = wp_remote_retrieve_body( $response );
|
||||
$result_output = json_decode( $body, true );
|
||||
if ( $response_code !== 200 || empty( $result_output ) ) {
|
||||
|
||||
$error_code = $response_code;
|
||||
|
||||
throw new Exception("PostSMTP GMAIL API Error: $error_message (HTTP Code: $error_code)");
|
||||
|
||||
}
|
||||
// ✅ Ensure email send response contains "data".
|
||||
if ( !isset( $result_output['data'] ) ) {
|
||||
throw new Exception( "PostSMTP GMAIL API Error: Missing 'data' key in response: " . print_r( $result_output, true ) );
|
||||
}
|
||||
|
||||
$result = $result_output['data'];
|
||||
}else{
|
||||
$googleApiMessage = new Message ();
|
||||
$googleService = $this->_config [self::SERVICE_OPTION];
|
||||
$googleClient = $googleService->getClient();
|
||||
$googleClient->setDefer(true);
|
||||
$result = $googleService->users_messages->send ( 'me', $googleApiMessage, array('uploadType' => 'resumable') );
|
||||
$chunkSizeBytes = 1 * 1024 * 1024;
|
||||
|
||||
// create mediafile upload
|
||||
$media = new MediaFileUpload(
|
||||
$googleClient,
|
||||
$result,
|
||||
'message/rfc822',
|
||||
$message,
|
||||
true,
|
||||
$chunkSizeBytes
|
||||
);
|
||||
$media->setFileSize($file_size);
|
||||
|
||||
$status = false;
|
||||
while (! $status) {
|
||||
$status = $media->nextChunk();
|
||||
}
|
||||
$result = false;
|
||||
|
||||
// Reset to the client to execute requests immediately in the future.
|
||||
$googleClient->setDefer(false);
|
||||
|
||||
$googleMessageId = $status->getId();
|
||||
}
|
||||
if ($this->logger->isInfo ()) {
|
||||
$this->logger->info ( sprintf ( 'Message %d accepted for delivery', PostmanState::getInstance ()->getSuccessfulDeliveries () + 1 ) );
|
||||
}
|
||||
$this->transcript = print_r ( $result, true );
|
||||
$this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
|
||||
$this->transcript .= $message;
|
||||
} catch ( Exception $e ) {
|
||||
$this->transcript = $e->getMessage ();
|
||||
$this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
|
||||
$this->transcript .= $message;
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
public function getMessage() {
|
||||
return $this->message;
|
||||
}
|
||||
public function getTranscript() {
|
||||
return $this->transcript;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format and fix headers
|
||||
*
|
||||
* Some SMTP servers do not strip BCC headers. Most clients do it themselves as do we.
|
||||
*
|
||||
* @access protected
|
||||
* @param array $headers
|
||||
* @return void
|
||||
* @throws Postman_Zend_Transport_Exception
|
||||
*/
|
||||
protected function _prepareHeaders($headers) {
|
||||
if (! $this->_mail) {
|
||||
/**
|
||||
*
|
||||
* @see Postman_Zend_Mail_Transport_Exception
|
||||
*/
|
||||
// require_once 'Zend/Mail/Transport/Exception.php';
|
||||
throw new Postman_Zend_Mail_Transport_Exception ( '_prepareHeaders requires a registered Postman_Zend_Mail object' );
|
||||
}
|
||||
|
||||
// google will unset the Bcc header for us.
|
||||
// unset ( $headers ['Bcc'] );
|
||||
|
||||
// Prepare headers
|
||||
parent::_prepareHeaders ( $headers );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
if (! interface_exists ( "PostmanMailEngine" )) {
|
||||
|
||||
interface PostmanMailEngine {
|
||||
public function getTranscript();
|
||||
public function send(PostmanMessage $message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,267 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'PostmanMailerSendMailEngine' ) ) {
|
||||
|
||||
require_once 'Services/MailerSend/Handler.php';
|
||||
|
||||
/**
|
||||
* Sends mail with the MailerSend API
|
||||
* https://mailersend.com/docs/API_Reference/Web_API/mail.html
|
||||
*
|
||||
* @author jasonhendriks
|
||||
*/
|
||||
class PostmanMailerSendMailEngine implements PostmanMailEngine {
|
||||
|
||||
// logger for all concrete classes - populate with setLogger($logger)
|
||||
protected $logger;
|
||||
|
||||
// the result
|
||||
private $transcript;
|
||||
|
||||
private $apiKey;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mixed $senderEmail
|
||||
* @param mixed $accessToken
|
||||
*/
|
||||
function __construct( $apiKey ) {
|
||||
assert( ! empty( $apiKey ) );
|
||||
$this->apiKey = $apiKey;
|
||||
|
||||
// create the logger
|
||||
$this->logger = new PostmanLogger( get_class( $this ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanSmtpEngine::send()
|
||||
*/
|
||||
public function send( PostmanMessage $message ) {
|
||||
$options = PostmanOptions::getInstance();
|
||||
|
||||
$mailersend = new PostmanMailerSend( $this->apiKey );
|
||||
$content = array();
|
||||
$recipients = array();
|
||||
$headers = array();
|
||||
|
||||
// add the From Header
|
||||
$sender = $message->getFromAddress();
|
||||
|
||||
$senderEmail = ! empty( $sender->getEmail() ) ? $sender->getEmail() : $options->getMessageSenderEmail();
|
||||
$senderName = ! empty( $sender->getName() ) ? $sender->getName() : $options->getMessageSenderName();
|
||||
|
||||
$content['from'] = array(
|
||||
'email' => $senderEmail,
|
||||
'name' => $senderName
|
||||
);
|
||||
|
||||
// now log it
|
||||
$sender->log( $this->logger, 'From' );
|
||||
|
||||
$duplicates = array();
|
||||
|
||||
// add the to recipients
|
||||
foreach ( ( array ) $message->getToRecipients() as $recipient ) {
|
||||
|
||||
if ( ! in_array( $recipient->getEmail(), $duplicates ) ) {
|
||||
|
||||
$content['to'][] = array(
|
||||
'email' => $recipient->getEmail(),
|
||||
'name' => $recipient->getName()
|
||||
);
|
||||
|
||||
$duplicates[] = $recipient->getEmail();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// add the subject
|
||||
if ( null !== $message->getSubject() ) {
|
||||
|
||||
$content['subject'] = $message->getSubject();
|
||||
|
||||
}
|
||||
|
||||
// add the message content
|
||||
|
||||
$textPart = $message->getBodyTextPart();
|
||||
if ( ! empty( $textPart ) ) {
|
||||
|
||||
$this->logger->debug( 'Adding body as text' );
|
||||
|
||||
$content['text'] = $textPart;
|
||||
|
||||
}
|
||||
|
||||
$htmlPart = $message->getBodyHtmlPart();
|
||||
|
||||
if ( ! empty( $htmlPart ) ) {
|
||||
|
||||
$this->logger->debug( 'Adding body as html' );
|
||||
|
||||
$content['html'] = $htmlPart;
|
||||
|
||||
|
||||
}
|
||||
|
||||
// add the reply-to
|
||||
$replyTo = $message->getReplyTo();
|
||||
// $replyTo is null or a PostmanEmailAddress object
|
||||
if ( isset( $replyTo ) ) {
|
||||
|
||||
$content['reply_to'] = array(
|
||||
'email' => $replyTo->getEmail(),
|
||||
'name' => $replyTo->getName()
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
// add the Postman signature - append it to whatever the user may have set
|
||||
if ( ! $options->isStealthModeEnabled() ) {
|
||||
$pluginData = apply_filters( 'postman_get_plugin_metadata', null );
|
||||
//$email->addHeader( 'X-Mailer', sprintf( 'Postman SMTP %s for WordPress (%s)', $pluginData ['version'], 'https://wordpress.org/plugins/post-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'] ) );
|
||||
$headers[$header ['name']] = $header['content'];
|
||||
}
|
||||
|
||||
// if the caller set a Content-Type header, use it
|
||||
$contentType = $message->getContentType();
|
||||
if ( ! empty( $contentType ) ) {
|
||||
$this->logger->debug( 'Some header keys are reserved. You may not include any of the following reserved headers: x-sg-id, x-sg-eid, received, dkim-signature, Content-Type, Content-Transfer-Encoding, To, From, Subject, Reply-To, CC, BCC.' );
|
||||
}
|
||||
|
||||
// add the cc recipients
|
||||
$ccEmails = array();
|
||||
foreach ( ( array ) $message->getCcRecipients() as $recipient ) {
|
||||
|
||||
if ( ! in_array( $recipient->getEmail(), $duplicates ) ) {
|
||||
|
||||
$recipient->log($this->logger, 'Cc');
|
||||
$content['personalizations'][0]['cc'][] = array(
|
||||
'email' => $recipient->getEmail(),
|
||||
'name' => $recipient->getName()
|
||||
);
|
||||
|
||||
$duplicates[] = $recipient->getEmail();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// add the bcc recipients
|
||||
$bccEmails = array();
|
||||
foreach ( ( array ) $message->getBccRecipients() as $recipient ) {
|
||||
|
||||
if ( ! in_array( $recipient->getEmail(), $duplicates ) ) {
|
||||
|
||||
$recipient->log($this->logger, 'Bcc');
|
||||
$content['personalizations'][0]['bcc'][] = array(
|
||||
'email' => $recipient->getEmail(),
|
||||
'name' => $recipient->getName()
|
||||
);
|
||||
|
||||
$duplicates[] = $recipient->getEmail();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
if( !empty( $headers ) ){
|
||||
// $content['headers'] = $headers;
|
||||
}
|
||||
|
||||
// add the messageId
|
||||
$messageId = '<' . $message->getMessageId() . '>';
|
||||
if ( ! empty( $messageId ) ) {
|
||||
//$email->addHeader( 'message-id', $messageId );
|
||||
}
|
||||
|
||||
// add attachments
|
||||
$this->logger->debug( 'Adding attachments' );
|
||||
|
||||
$attachments = $this->addAttachmentsToMail( $message );
|
||||
|
||||
if( !empty( $attachments ) ) {
|
||||
|
||||
$content['attachments'] = $this->addAttachmentsToMail( $message );
|
||||
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
|
||||
// send the message
|
||||
if ( $this->logger->isDebug() ) {
|
||||
$this->logger->debug( 'Sending mail' );
|
||||
}
|
||||
|
||||
$response = $mailersend->send( $content );
|
||||
|
||||
$this->transcript = print_r( $response, true );
|
||||
$this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
|
||||
$this->transcript .= print_r( $content, true );
|
||||
$this->logger->debug( 'Transcript=' . $this->transcript );
|
||||
|
||||
} catch ( Exception $e ) {
|
||||
|
||||
$this->transcript = $e->getMessage();
|
||||
$this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
|
||||
$this->transcript .= print_r( $content, true );
|
||||
$this->logger->debug( 'Transcript=' . $this->transcript );
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add attachments to the message
|
||||
*
|
||||
* @param Postman_Zend_Mail $mail
|
||||
*/
|
||||
private function addAttachmentsToMail( PostmanMessage $message ) {
|
||||
$attachments = $message->getAttachments();
|
||||
if ( ! is_array( $attachments ) ) {
|
||||
// WordPress may a single filename or a newline-delimited string list of multiple filenames
|
||||
$attArray = explode( PHP_EOL, $attachments );
|
||||
} else {
|
||||
$attArray = $attachments;
|
||||
}
|
||||
// otherwise WordPress sends an array
|
||||
$attachments = array();
|
||||
foreach ( $attArray as $file ) {
|
||||
if ( ! empty( $file ) ) {
|
||||
$this->logger->debug( 'Adding attachment: ' . $file );
|
||||
|
||||
$file_name = basename( $file );
|
||||
$file_parts = explode( '.', $file_name );
|
||||
$file_type = wp_check_filetype( $file );
|
||||
$attachments[] = array(
|
||||
'content' => base64_encode( file_get_contents( $file ) ),
|
||||
'type' => $file_type['type'],
|
||||
'filename' => $file_name,
|
||||
'disposition' => 'attachment',
|
||||
'name' => $file_parts[0],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $attachments;
|
||||
}
|
||||
|
||||
// return the SMTP session transcript
|
||||
public function getTranscript() {
|
||||
return $this->transcript;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
require_once 'PostmanModuleTransport.php';
|
||||
/**
|
||||
* Postman MailerSend module
|
||||
*
|
||||
* @author jasonhendriks
|
||||
*
|
||||
*/
|
||||
class PostmanMailerSendTransport extends PostmanAbstractModuleTransport implements PostmanModuleTransport {
|
||||
const SLUG = 'mailersend_api';
|
||||
const PORT = 443;
|
||||
const HOST = 'api.mailersend.com';
|
||||
const PRIORITY = 48000;
|
||||
const MAILERSEND_AUTH_OPTIONS = 'postman_mailersend_auth_options';
|
||||
const MAILERSEND_AUTH_SECTION = 'postman_mailersend_auth_section';
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mixed $rootPluginFilenameAndPath
|
||||
*/
|
||||
public function __construct($rootPluginFilenameAndPath) {
|
||||
parent::__construct ( $rootPluginFilenameAndPath );
|
||||
|
||||
// add a hook on the plugins_loaded event
|
||||
add_action ( 'admin_init', array (
|
||||
$this,
|
||||
'on_admin_init'
|
||||
) );
|
||||
}
|
||||
public function getProtocol() {
|
||||
return 'https';
|
||||
}
|
||||
|
||||
// this should be standard across all transports
|
||||
public function getSlug() {
|
||||
return self::SLUG;
|
||||
}
|
||||
public function getName() {
|
||||
return __ ( 'MailerSend API', 'post-smtp' );
|
||||
}
|
||||
/**
|
||||
* v0.2.1
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getHostname() {
|
||||
return self::HOST;
|
||||
}
|
||||
/**
|
||||
* v0.2.1
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getPort() {
|
||||
return self::PORT;
|
||||
}
|
||||
/**
|
||||
* v1.7.0
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTransportType() {
|
||||
return 'MailerSend_api';
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanModuleTransport::createMailEngine()
|
||||
*/
|
||||
public function createMailEngine() {
|
||||
$apiKey = $this->options->getMailerSendApiKey ();
|
||||
require_once 'PostmanMailerSendMailEngine.php';
|
||||
$engine = new PostmanMailerSendMailEngine ( $apiKey );
|
||||
return $engine;
|
||||
}
|
||||
public function getDeliveryDetails() {
|
||||
/* translators: where (1) is the secure icon and (2) is the transport name */
|
||||
return sprintf ( __ ( 'Postman will send mail via the <b>%1$s %2$s</b>.', 'post-smtp' ), '🔐', $this->getName () );
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mixed $data
|
||||
*/
|
||||
public function prepareOptionsForExport($data) {
|
||||
$data = parent::prepareOptionsForExport ( $data );
|
||||
$data [PostmanOptions::MAILERSEND_API_KEY] = PostmanOptions::getInstance ()->getMailerSendApiKey ();
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanTransport::getMisconfigurationMessage()
|
||||
*/
|
||||
protected function validateTransportConfiguration() {
|
||||
$messages = parent::validateTransportConfiguration ();
|
||||
$apiKey = $this->options->getMailerSendApiKey ();
|
||||
if (empty ( $apiKey )) {
|
||||
array_push ( $messages, __ ( 'API Key can not be empty', 'post-smtp' ) . '.' );
|
||||
$this->setNotConfiguredAndReady ();
|
||||
}
|
||||
if (! $this->isSenderConfigured ()) {
|
||||
array_push ( $messages, __ ( 'Message From Address can not be empty', 'post-smtp' ) . '.' );
|
||||
$this->setNotConfiguredAndReady ();
|
||||
}
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanModuleTransport::getConfigurationBid()
|
||||
*/
|
||||
public function getConfigurationBid(PostmanWizardSocket $hostData, $userAuthOverride, $originalSmtpServer) {
|
||||
$recommendation = array ();
|
||||
$recommendation ['priority'] = 0;
|
||||
$recommendation ['transport'] = self::SLUG;
|
||||
$recommendation ['hostname'] = null; // scribe looks this
|
||||
$recommendation ['label'] = $this->getName ();
|
||||
$recommendation['logo_url'] = $this->getLogoURL();
|
||||
|
||||
if ($hostData->hostname == self::HOST && $hostData->port == self::PORT) {
|
||||
$recommendation ['priority'] = self::PRIORITY;
|
||||
/* translators: where variables are (1) transport name (2) host and (3) port */
|
||||
$recommendation ['message'] = sprintf ( __ ( ('Postman recommends the %1$s to host %2$s on port %3$d.') ), $this->getName (), self::HOST, self::PORT );
|
||||
}
|
||||
return $recommendation;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mixed $hostname
|
||||
* @param mixed $response
|
||||
*/
|
||||
public function populateConfiguration($hostname) {
|
||||
$response = parent::populateConfiguration ( $hostname );
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function createOverrideMenu(PostmanWizardSocket $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride) {
|
||||
$overrideItem = parent::createOverrideMenu ( $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride );
|
||||
// push the authentication options into the $overrideItem structure
|
||||
$overrideItem ['auth_items'] = array (
|
||||
array (
|
||||
'selected' => true,
|
||||
'name' => __ ( 'API Key', 'post-smtp' ),
|
||||
'value' => 'api_key'
|
||||
)
|
||||
);
|
||||
return $overrideItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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->addSettings ();
|
||||
$this->registerStylesAndScripts ();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* What follows in the code responsible for creating the Admin Settings page
|
||||
*/
|
||||
|
||||
/**
|
||||
*/
|
||||
public function addSettings() {
|
||||
// the MailerSend Auth section
|
||||
add_settings_section ( PostmanMailerSendTransport::MAILERSEND_AUTH_SECTION, __ ( 'Authentication', 'post-smtp' ), array (
|
||||
$this,
|
||||
'printMailerSendAuthSectionInfo'
|
||||
), PostmanMailerSendTransport::MAILERSEND_AUTH_OPTIONS );
|
||||
|
||||
add_settings_field ( PostmanOptions::MAILERSEND_API_KEY, __ ( 'API Key', 'post-smtp' ), array (
|
||||
$this,
|
||||
'mailersend_api_key_callback'
|
||||
), PostmanMailerSendTransport::MAILERSEND_AUTH_OPTIONS, PostmanMailerSendTransport::MAILERSEND_AUTH_SECTION );
|
||||
|
||||
}
|
||||
public function printMailerSendAuthSectionInfo() {
|
||||
/* Translators: Where (1) is the service URL and (2) is the service name and (3) is a api key URL */
|
||||
printf ( '<p id="wizard_mailersend_auth_help">%s</p>', sprintf ( __ ( 'Create an account at <a href="%1$s" target="_blank">%2$s</a> and enter <a href="%3$s" target="_blank">an API key</a> below.', 'post-smtp' ), 'https://mailersend.com', 'MailerSend.com', 'https://app.mailersend.com/settings/api_keys' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function mailersend_api_key_callback() {
|
||||
printf ( '<input type="password" autocomplete="off" id="mailersend_api_key" name="postman_options[mailersend_api_key]" value="%s" size="60" class="required ps-input ps-w-75" placeholder="%s"/>', null !== $this->options->getMailerSendApiKey () ? esc_attr ( PostmanUtils::obfuscatePassword ( $this->options->getMailerSendApiKey () ) ) : '', __ ( 'Required', 'post-smtp' ) );
|
||||
print ' <input type="button" id="toggleMailerSendApiKey" value="Show Password" class="button button-secondary" style="visibility:hidden" />';
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function registerStylesAndScripts() {
|
||||
// register the stylesheet and javascript external resources
|
||||
$pluginData = apply_filters ( 'postman_get_plugin_metadata', null );
|
||||
wp_register_script ( 'postman_mailersend_script', plugins_url ( 'Postman/Postman-Mail/postman_mailersend.js', $this->rootPluginFilenameAndPath ), array (
|
||||
PostmanViewController::JQUERY_SCRIPT,
|
||||
'jquery_validation',
|
||||
PostmanViewController::POSTMAN_SCRIPT
|
||||
), $pluginData ['version'] );
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function enqueueScript() {
|
||||
wp_enqueue_script ( 'postman_mailersend_script' );
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function printWizardAuthenticationStep() {
|
||||
print '<section class="wizard_mailersend">';
|
||||
$this->printMailerSendAuthSectionInfo ();
|
||||
printf ( '<label for="api_key">%s</label>', __ ( 'API Key', 'post-smtp' ) );
|
||||
print '<br />';
|
||||
print $this->mailersend_api_key_callback ();
|
||||
print '</section>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Socket's logo
|
||||
*
|
||||
* @since 3.3.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getLogoURL() {
|
||||
|
||||
return POST_SMTP_ASSETS . "images/logos/mailersend.png";
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true, to prevent from errors because it's default Module Transport.
|
||||
*
|
||||
* @since 3.3.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function has_granted() {
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
if( !class_exists( 'PostmanMailerooMailEngine' ) ):
|
||||
|
||||
require_once 'Services/Maileroo/Handler.php';
|
||||
|
||||
class PostmanMailerooMailEngine implements PostmanMailEngine {
|
||||
|
||||
protected $logger;
|
||||
private $transcript;
|
||||
private $api_key;
|
||||
|
||||
public function __construct( $api_key ) {
|
||||
assert( !empty( $api_key ) );
|
||||
$this->api_key = $api_key;
|
||||
$this->logger = new PostmanLogger( get_class( $this ) );
|
||||
}
|
||||
|
||||
public function getTranscript() {
|
||||
return $this->transcript;
|
||||
}
|
||||
|
||||
private function addAttachmentsToMail( PostmanMessage $message ) {
|
||||
$attachments = $message->getAttachments();
|
||||
$attArray = is_array( $attachments ) ? $attachments : explode( PHP_EOL, $attachments );
|
||||
$result = [];
|
||||
foreach ( $attArray as $file ) {
|
||||
if ( ! empty( $file ) ) {
|
||||
$this->logger->debug( 'Adding attachment: ' . $file );
|
||||
$fileName = basename( $file );
|
||||
$fileType = wp_check_filetype( $file );
|
||||
$result[] = [
|
||||
'content' => base64_encode( file_get_contents( $file ) ),
|
||||
'type' => $fileType['type'],
|
||||
'filename' => $fileName,
|
||||
'disposition' => 'attachment',
|
||||
'name' => pathinfo( $fileName, PATHINFO_FILENAME ),
|
||||
];
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function send( PostmanMessage $message ) {
|
||||
$options = PostmanOptions::getInstance();
|
||||
$maileroo = new PostmanMaileroo( $this->api_key );
|
||||
|
||||
$recipients = [];
|
||||
$duplicates = [];
|
||||
|
||||
$sender = $message->getFromAddress();
|
||||
$senderEmail = ! empty( $sender->getEmail() ) ? $sender->getEmail() : $options->getMessageSenderEmail();
|
||||
$senderName = ! empty( $sender->getName() ) ? $sender->getName() : $options->getMessageSenderName();
|
||||
$sender->log( $this->logger, 'From' );
|
||||
|
||||
foreach ( (array) $message->getToRecipients() as $recipient ) {
|
||||
if ( ! in_array( $recipient->getEmail(), $duplicates ) ) {
|
||||
$recipients[] = $recipient->getEmail();
|
||||
$duplicates[] = $recipient->getEmail();
|
||||
}
|
||||
}
|
||||
|
||||
$subject = $message->getSubject();
|
||||
$textPart = $message->getBodyTextPart();
|
||||
$htmlPart = $message->getBodyHtmlPart();
|
||||
$htmlContent = ! empty( $htmlPart ) ? $htmlPart : nl2br( $textPart );
|
||||
if ( empty( $htmlContent ) ) {
|
||||
$htmlContent = '<p>(No content)</p>';
|
||||
}
|
||||
|
||||
$content = [
|
||||
'from' => [
|
||||
'address' => $senderEmail,
|
||||
'display_name' => $senderName,
|
||||
],
|
||||
'to' => array_map(function($email) { return ['address' => $email]; }, $recipients),
|
||||
'subject' => $subject,
|
||||
'html' => $htmlContent,
|
||||
'text' => wp_strip_all_tags( $textPart ?: $htmlPart ),
|
||||
];
|
||||
|
||||
$attachments = $this->addAttachmentsToMail( $message );
|
||||
if ( ! empty( $attachments ) ) {
|
||||
$content['attachments'] = $attachments;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->logger->debug( 'Sending mail via Maileroo' );
|
||||
$response = $maileroo->send( $content );
|
||||
$responseCode = wp_remote_retrieve_response_code( $response );
|
||||
$responseBody = wp_remote_retrieve_body( $response );
|
||||
|
||||
if ( $responseCode === 200 || $responseCode === 202 ) {
|
||||
$this->transcript = 'Email sent successfully.' . PHP_EOL;
|
||||
$this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS . PHP_EOL;
|
||||
$this->transcript .= print_r( $content, true );
|
||||
$this->logger->debug( 'Transcript=' . $this->transcript );
|
||||
} else {
|
||||
$decodedBody = json_decode( $responseBody, true );
|
||||
$errorMessage = $this->extractErrorMessage( $decodedBody, $responseCode );
|
||||
throw new Exception( $errorMessage );
|
||||
}
|
||||
} catch ( Exception $e ) {
|
||||
$this->transcript = $e->getMessage() . PHP_EOL;
|
||||
$this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS . PHP_EOL;
|
||||
$this->transcript .= print_r( $content, true );
|
||||
$this->logger->debug( 'Transcript=' . $this->transcript );
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
private function extractErrorMessage( $decodedBody, $responseCode ) {
|
||||
if ( is_array( $decodedBody ) ) {
|
||||
if ( isset( $decodedBody['message'] ) && is_string( $decodedBody['message'] ) ) {
|
||||
return $decodedBody['message'];
|
||||
}
|
||||
if ( isset( $decodedBody['error'] ) ) {
|
||||
return is_string( $decodedBody['error'] )
|
||||
? $decodedBody['error']
|
||||
: ( $decodedBody['error']['message'] ?? $this->getErrorMessageFromCode( $responseCode ) );
|
||||
}
|
||||
}
|
||||
return $this->getErrorMessageFromCode( $responseCode );
|
||||
}
|
||||
|
||||
private function getErrorMessageFromCode( $response_code ) {
|
||||
switch ( $response_code ) {
|
||||
case 400:
|
||||
return __( 'Bad request. Please check your email data.', 'maileroo' );
|
||||
case 401:
|
||||
return __( 'Unauthorized. Please check your API key.', 'maileroo' );
|
||||
case 403:
|
||||
return __( 'Forbidden. Access denied.', 'maileroo' );
|
||||
case 404:
|
||||
return __( 'Not found. Please check the API endpoint.', 'maileroo' );
|
||||
case 422:
|
||||
return __( 'Domain verification required. Your sending domain must be verified in Maileroo before you can send emails. Please verify your domain in your Maileroo dashboard.', 'maileroo' );
|
||||
case 429:
|
||||
return __( 'Rate limit exceeded. Please try again later.', 'maileroo' );
|
||||
case 500:
|
||||
return __( 'Internal server error. Please try again later.', 'maileroo' );
|
||||
default:
|
||||
return sprintf( __( 'HTTP error %d occurred.', 'maileroo' ), $response_code );
|
||||
}
|
||||
}
|
||||
}
|
||||
endif;
|
||||
@@ -0,0 +1,180 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once 'PostmanModuleTransport.php';
|
||||
|
||||
/**
|
||||
* Postman Maileroo
|
||||
* @since 2.1
|
||||
* @version 1.0
|
||||
*/
|
||||
if( !class_exists( 'PostmanMailerooTransport' ) ):
|
||||
class PostmanMailerooTransport extends PostmanAbstractModuleTransport implements PostmanModuleTransport {
|
||||
|
||||
const SLUG = 'maileroo_api';
|
||||
const PORT = 587;
|
||||
const HOST = 'smtp.maileroo.com';
|
||||
const PRIORITY = 50000;
|
||||
const MAILEROO_AUTH_OPTIONS = 'postman_maileroo_auth_options';
|
||||
const MAILEROO_AUTH_SECTION = 'postman_maileroo_auth_section';
|
||||
|
||||
public function __construct( $rootPluginFilenameAndPath ) {
|
||||
parent::__construct ( $rootPluginFilenameAndPath );
|
||||
add_action ( 'admin_init', array ( $this, 'on_admin_init' ) );
|
||||
}
|
||||
|
||||
public function getPort() {
|
||||
return self::PORT;
|
||||
}
|
||||
|
||||
public function getSlug() {
|
||||
return self::SLUG;
|
||||
}
|
||||
|
||||
public function getProtocol() {
|
||||
return 'https';
|
||||
}
|
||||
|
||||
public function getName() {
|
||||
return __('Maileroo API', 'post-smtp');
|
||||
}
|
||||
|
||||
public function getHostname() {
|
||||
return self::HOST;
|
||||
}
|
||||
|
||||
public function getTransportType() {
|
||||
return 'Maileroo_api';
|
||||
}
|
||||
|
||||
public function getDeliveryDetails() {
|
||||
return sprintf(__('Postman will send mail via the <b>%1$s %2$s</b>.', 'post-smtp'), '🔐', $this->getName());
|
||||
}
|
||||
|
||||
protected function validateTransportConfiguration() {
|
||||
$messages = parent::validateTransportConfiguration();
|
||||
$apiKey = $this->options->getMailerooApiKey();
|
||||
if (empty($apiKey)) {
|
||||
array_push($messages, __('API Key can not be empty', 'post-smtp') . '.');
|
||||
$this->setNotConfiguredAndReady();
|
||||
}
|
||||
if (!$this->isSenderConfigured()) {
|
||||
array_push($messages, __('Message From Address can not be empty', 'post-smtp') . '.');
|
||||
$this->setNotConfiguredAndReady();
|
||||
}
|
||||
return $messages;
|
||||
}
|
||||
|
||||
public function getConfigurationBid(PostmanWizardSocket $hostData, $userAuthOverride, $originalSmtpServer) {
|
||||
$recommendation = array();
|
||||
$recommendation['priority'] = 0;
|
||||
$recommendation['transport'] = self::SLUG;
|
||||
$recommendation['hostname'] = null;
|
||||
$recommendation['label'] = $this->getName();
|
||||
$recommendation['logo_url'] = $this->getLogoURL();
|
||||
if ($hostData->hostname == self::HOST && $hostData->port == self::PORT) {
|
||||
$recommendation['priority'] = self::PRIORITY;
|
||||
$recommendation['message'] = sprintf(__('Postman recommends the %1$s to host %2$s on port %3$d.'), $this->getName(), self::HOST, self::PORT);
|
||||
}
|
||||
return $recommendation;
|
||||
}
|
||||
|
||||
public function on_admin_init() {
|
||||
if (PostmanUtils::isAdmin()) {
|
||||
$this->addSettings();
|
||||
$this->registerStylesAndScripts();
|
||||
}
|
||||
}
|
||||
|
||||
public function addSettings() {
|
||||
add_settings_section(self::MAILEROO_AUTH_SECTION, __('Authentication', 'post-smtp'), array($this, 'printMailerooAuthSectionInfo'), self::MAILEROO_AUTH_OPTIONS);
|
||||
add_settings_field('maileroo_api_key', __('API Key', 'post-smtp'), array($this, 'maileroo_api_key_callback'), self::MAILEROO_AUTH_OPTIONS, self::MAILEROO_AUTH_SECTION);
|
||||
}
|
||||
|
||||
public function printMailerooAuthSectionInfo() {
|
||||
printf('<p id="wizard_maileroo_auth_help">%s</p>', sprintf(__('Enter your Maileroo API key and endpoint below.', 'post-smtp')));
|
||||
}
|
||||
|
||||
public function maileroo_api_key_callback() {
|
||||
printf('<input type="password" autocomplete="off" id="maileroo_api_key" name="postman_options[maileroo_api_key]" value="%s" size="60" class="required ps-input ps-w-75" placeholder="%s"/>', null !== $this->options->getMailerooApiKey() ? esc_attr(PostmanUtils::obfuscatePassword($this->options->getMailerooApiKey())) : '', __('Required', 'post-smtp'));
|
||||
print ' <input type="button" id="toggleMailerooApiKey" value="Show Password" class="button button-secondary" style="visibility:hidden" />';
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function registerStylesAndScripts() {
|
||||
|
||||
// register the stylesheet and javascript external resources
|
||||
$pluginData = apply_filters ( 'postman_get_plugin_metadata', null );
|
||||
wp_register_script (
|
||||
'postman-maileroo',
|
||||
plugins_url ( 'Postman/Postman-Mail/postman-maileroo.js', $this->rootPluginFilenameAndPath ),
|
||||
array (
|
||||
PostmanViewController::JQUERY_SCRIPT,
|
||||
'jquery_validation',
|
||||
PostmanViewController::POSTMAN_SCRIPT
|
||||
),
|
||||
$pluginData['version']
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function enqueueScript() {
|
||||
|
||||
wp_enqueue_script( 'postman-maileroo' );
|
||||
|
||||
}
|
||||
|
||||
public function printWizardAuthenticationStep() {
|
||||
print '<section class="wizard_maileroo">';
|
||||
$this->printMailerooAuthSectionInfo();
|
||||
printf('<label for="api_key">%s</label>', __('API Key', 'post-smtp'));
|
||||
print '<br />';
|
||||
print $this->maileroo_api_key_callback();
|
||||
print '</section>';
|
||||
}
|
||||
|
||||
public function getLogoURL() {
|
||||
return POST_SMTP_ASSETS . "images/logos/maileroo.png";
|
||||
}
|
||||
|
||||
public function has_granted() {
|
||||
return true;
|
||||
}
|
||||
public function getHost() {
|
||||
return self::HOST;
|
||||
}
|
||||
|
||||
public function getPriority() {
|
||||
return self::PRIORITY;
|
||||
}
|
||||
|
||||
public function getAuthOptionsName() {
|
||||
return self::MAILEROO_AUTH_OPTIONS;
|
||||
}
|
||||
|
||||
public function getAuthSectionName() {
|
||||
return self::MAILEROO_AUTH_SECTION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create Maileroo mail engine instance
|
||||
* @since 2.1
|
||||
* @version 1.0
|
||||
*/
|
||||
public function createMailEngine() {
|
||||
$api_key = $this->options->getMailerooApiKey();
|
||||
require_once 'PostmanMailerooMailEngine.php';
|
||||
$engine = new PostmanMailerooMailEngine( $api_key );
|
||||
return $engine;
|
||||
}
|
||||
}
|
||||
endif;
|
||||
@@ -0,0 +1,247 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
require_once 'Services/MailGun/Handler.php';
|
||||
|
||||
if ( ! class_exists( 'PostmanMailgunMailEngine' ) ) {
|
||||
|
||||
/**
|
||||
* Sends mail with the SendGrid API
|
||||
* https://sendgrid.com/docs/API_Reference/Web_API/mail.html
|
||||
*
|
||||
* @author jasonhendriks
|
||||
*/
|
||||
class PostmanMailgunMailEngine implements PostmanMailEngine {
|
||||
|
||||
// logger for all concrete classes - populate with setLogger($logger)
|
||||
protected $logger;
|
||||
|
||||
// the result
|
||||
private $transcript;
|
||||
|
||||
private $apiKey;
|
||||
private $domainName;
|
||||
private $mailgunMessage;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mixed $senderEmail
|
||||
* @param mixed $accessToken
|
||||
*/
|
||||
function __construct( $apiKey, $domainName ) {
|
||||
assert( ! empty( $apiKey ) );
|
||||
$this->apiKey = $apiKey;
|
||||
$this->domainName = $domainName;
|
||||
|
||||
// create the logger
|
||||
$this->logger = new PostmanLogger( get_class( $this ) );
|
||||
$this->mailgunMessage = array(
|
||||
'from' => '',
|
||||
'to' => '',
|
||||
'subject' => '',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanSmtpEngine::send()
|
||||
*/
|
||||
public function send( PostmanMessage $message ) {
|
||||
|
||||
if ( $this->logger->isDebug() ) {
|
||||
$this->logger->debug( 'Creating Mailgun service with apiKey=' . $this->apiKey );
|
||||
}
|
||||
|
||||
$options = PostmanOptions::getInstance();
|
||||
$region = $options->getMailgunRegion();
|
||||
|
||||
$mailgun = new PostmanMailGun( $this->apiKey, $region, $this->domainName );
|
||||
$this->get_email_body( $message );
|
||||
$body = $this->mailgunMessage;
|
||||
|
||||
$result = array();
|
||||
try {
|
||||
$response = $mailgun->send( $body );
|
||||
// send the message
|
||||
if ( $this->logger->isDebug() ) {
|
||||
$this->logger->debug( 'Sending mail' );
|
||||
}
|
||||
|
||||
if ( $this->logger->isInfo() ) {
|
||||
$this->logger->info( sprintf( 'Message %d accepted for delivery', PostmanState::getInstance()->getSuccessfulDeliveries() + 1 ) );
|
||||
}
|
||||
|
||||
$this->transcript = print_r( $result, true );
|
||||
$this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
|
||||
$this->transcript .= print_r( $this->mailgunMessage, true );
|
||||
} catch ( Exception $e ) {
|
||||
$this->transcript = $e->getMessage();
|
||||
$this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
|
||||
$this->transcript .= print_r( $this->mailgunMessage, true );
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
private function getRecipientVariables( $emails ) {
|
||||
$recipient_variables = array();
|
||||
foreach ( $emails as $key => $email ) {
|
||||
$recipient_variables[$email] = array( 'id' => $key );
|
||||
}
|
||||
|
||||
return json_encode( $recipient_variables );
|
||||
}
|
||||
|
||||
private function addHeader( $name, $value, $deprecated = '' ) {
|
||||
if ( $value && ! empty( $value ) ) {
|
||||
$this->mailgunMessage['h:' . $name] = preg_replace('/.*:\s?/', '', $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add attachments to the message
|
||||
*
|
||||
* @param Postman_Zend_Mail $mail
|
||||
*/
|
||||
private function addAttachmentsToMail( PostmanMessage $message ) {
|
||||
$attachments = $message->getAttachments();
|
||||
|
||||
if ( ! is_array( $attachments ) ) {
|
||||
// WordPress may a single filename or a newline-delimited string list of multiple filenames
|
||||
$attArray[] = explode( PHP_EOL, $attachments );
|
||||
} else {
|
||||
$attArray = $attachments;
|
||||
}
|
||||
|
||||
$attachments = array();
|
||||
foreach ( $attArray as $file ) {
|
||||
if ( ! empty( $file ) ) {
|
||||
$this->logger->debug( 'Adding attachment: ' . $file );
|
||||
$attachments[] = array( 'filePath' => $file );
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $attachments ) ) {
|
||||
if ( $this->logger->isTrace() ) {
|
||||
$this->logger->trace( $attachments );
|
||||
}
|
||||
$this->mailgunMessage['attachment'] = $attachments;
|
||||
}
|
||||
}
|
||||
|
||||
// return the SMTP session transcript
|
||||
public function getTranscript() {
|
||||
return $this->transcript;
|
||||
}
|
||||
|
||||
private function get_email_body( $message ) {
|
||||
|
||||
if( is_a( $message, 'PostmanMessage' ) ) {
|
||||
$options = PostmanOptions::getInstance();
|
||||
|
||||
// add the From Header
|
||||
$sender = $message->getFromAddress();
|
||||
{
|
||||
|
||||
$senderEmail = !empty( $sender->getEmail() ) ? $sender->getEmail() : $options->getMessageSenderEmail();
|
||||
$senderName = !empty( $sender->getName() ) ? $sender->getName() : $options->getMessageSenderName();
|
||||
|
||||
$this->mailgunMessage ['from'] = "{$senderName} <{$senderEmail}>";
|
||||
// now log it
|
||||
$sender->log( $this->logger, 'From' );
|
||||
}
|
||||
|
||||
// add the to recipients
|
||||
$recipients = array();
|
||||
foreach ( ( array ) $message->getToRecipients() as $recipient ) {
|
||||
$recipient->log( $this->logger, 'To' );
|
||||
$recipients[] = $recipient->getEmail();
|
||||
}
|
||||
$this->mailgunMessage['to'] = $recipients;
|
||||
|
||||
// add the subject
|
||||
if ( null !== $message->getSubject() ) {
|
||||
$this->mailgunMessage ['subject'] = $message->getSubject();
|
||||
}
|
||||
|
||||
{ // add the message content
|
||||
$textPart = $message->getBodyTextPart();
|
||||
if ( ! empty( $textPart ) ) {
|
||||
$this->logger->debug( 'Adding body as text' );
|
||||
$this->mailgunMessage ['text'] = $textPart;
|
||||
}
|
||||
|
||||
$htmlPart = $message->getBodyHtmlPart();
|
||||
if ( ! empty( $htmlPart ) ) {
|
||||
$this->logger->debug( 'Adding body as html' );
|
||||
$this->mailgunMessage ['html'] = $htmlPart;
|
||||
}
|
||||
}
|
||||
|
||||
// add the reply-to
|
||||
$replyTo = $message->getReplyTo();
|
||||
// $replyTo is null or a PostmanEmailAddress object
|
||||
if ( isset( $replyTo ) ) {
|
||||
$this->addHeader( 'reply-to', $replyTo->format() );
|
||||
}
|
||||
|
||||
// add the Postman signature - append it to whatever the user may have set
|
||||
if ( ! $options->isStealthModeEnabled() ) {
|
||||
$pluginData = apply_filters( 'postman_get_plugin_metadata', null );
|
||||
$this->addHeader( 'X-Mailer', sprintf( 'Postman SMTP %s for WordPress (%s)', $pluginData ['version'], 'https://wordpress.org/plugins/post-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'] ) );
|
||||
$this->addHeader( $header ['name'], $header ['content'], true );
|
||||
}
|
||||
|
||||
// add the messageId
|
||||
$messageId = $message->getMessageId();
|
||||
if ( ! empty( $messageId ) ) {
|
||||
$this->addHeader( 'message-id', $messageId );
|
||||
}
|
||||
|
||||
// if the caller set a Content-Type header, use it
|
||||
$contentType = $message->getContentType();
|
||||
if ( ! empty( $contentType ) ) {
|
||||
$this->logger->debug( 'Adding content-type ' . $contentType );
|
||||
$this->addHeader( 'Content-Type', $contentType );
|
||||
}
|
||||
|
||||
// add the cc recipients
|
||||
$recipients = array();
|
||||
foreach ( ( array ) $message->getCcRecipients() as $recipient ) {
|
||||
$recipient->log( $this->logger, 'Cc' );
|
||||
$recipients[] = $recipient->getEmail();
|
||||
}
|
||||
$this->mailgunMessage['cc'] = implode( ',', $recipients );
|
||||
|
||||
// add the bcc recipients
|
||||
$recipients = array();
|
||||
foreach ( ( array ) $message->getBccRecipients() as $recipient ) {
|
||||
$recipient->log( $this->logger, 'Bcc' );
|
||||
$recipients[] = $recipient->getEmail();
|
||||
}
|
||||
$this->mailgunMessage['bcc'] = implode( ',', $recipients );
|
||||
|
||||
// add attachments
|
||||
$this->logger->debug( 'Adding attachments' );
|
||||
$this->addAttachmentsToMail( $message );
|
||||
|
||||
// add the date
|
||||
$date = $message->getDate();
|
||||
if ( ! empty( $date ) ) {
|
||||
$this->addHeader( 'date', $message->getDate() );
|
||||
}
|
||||
|
||||
// add the Sender Header, overriding what the user may have set
|
||||
$this->addHeader( 'Sender', $options->getEnvelopeSender() );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,295 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
require_once 'PostmanModuleTransport.php';
|
||||
/**
|
||||
* Postman Mailgun module
|
||||
*
|
||||
* @author jasonhendriks
|
||||
*/
|
||||
class PostmanMailgunTransport extends PostmanAbstractModuleTransport implements PostmanModuleTransport {
|
||||
const SLUG = 'mailgun_api';
|
||||
const PORT = 443;
|
||||
const HOST = 'api.mailgun.net';
|
||||
const EU_REGION = 'api.eu.mailgun.net';
|
||||
const PRIORITY = 47000;
|
||||
const MAILGUN_AUTH_OPTIONS = 'postman_mailgun_auth_options';
|
||||
const MAILGUN_AUTH_SECTION = 'postman_mailgun_auth_section';
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mixed $rootPluginFilenameAndPath
|
||||
*/
|
||||
public function __construct( $rootPluginFilenameAndPath ) {
|
||||
parent::__construct( $rootPluginFilenameAndPath );
|
||||
|
||||
// add a hook on the plugins_loaded event
|
||||
add_action( 'admin_init', array(
|
||||
$this,
|
||||
'on_admin_init',
|
||||
) );
|
||||
}
|
||||
public function getProtocol() {
|
||||
return 'https';
|
||||
}
|
||||
|
||||
// this should be standard across all transports
|
||||
public function getSlug() {
|
||||
return self::SLUG;
|
||||
}
|
||||
public function getName() {
|
||||
return __( 'Mailgun API', 'post-smtp' );
|
||||
}
|
||||
/**
|
||||
* v0.2.1
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getHostname() {
|
||||
return ! is_null( $this->options->getMailgunRegion() ) ? self::EU_REGION : self::HOST;
|
||||
}
|
||||
/**
|
||||
* v0.2.1
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getPort() {
|
||||
return self::PORT;
|
||||
}
|
||||
/**
|
||||
* v1.7.0
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTransportType() {
|
||||
return 'Mailgun_api';
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanModuleTransport::createMailEngine()
|
||||
*/
|
||||
public function createMailEngine() {
|
||||
$apiKey = $this->options->getMailgunApiKey();
|
||||
$domainName = $this->options->getMailgunDomainName();
|
||||
|
||||
require_once 'PostmanMailgunMailEngine.php';
|
||||
$engine = new PostmanMailgunMailEngine( $apiKey, $domainName );
|
||||
return $engine;
|
||||
}
|
||||
public function getDeliveryDetails() {
|
||||
/* translators: where (1) is the secure icon and (2) is the transport name */
|
||||
return sprintf( __( 'Post SMTP will send mail via the <b>%1$s %2$s</b>.', 'post-smtp' ), '🔐', $this->getName() );
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mixed $data
|
||||
*/
|
||||
public function prepareOptionsForExport( $data ) {
|
||||
$data = parent::prepareOptionsForExport( $data );
|
||||
$data [ PostmanOptions::MAILGUN_API_KEY ] = PostmanOptions::getInstance()->getMailgunApiKey();
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanTransport::getMisconfigurationMessage()
|
||||
*/
|
||||
protected function validateTransportConfiguration() {
|
||||
$messages = parent::validateTransportConfiguration();
|
||||
$apiKey = $this->options->getMailgunApiKey();
|
||||
$domainName = $this->options->getMailgunDomainName();
|
||||
|
||||
if ( empty( $apiKey ) ) {
|
||||
array_push( $messages, __( 'API Key can not be empty', 'post-smtp' ) . '.' );
|
||||
$this->setNotConfiguredAndReady();
|
||||
}
|
||||
|
||||
if ( empty( $domainName ) ) {
|
||||
array_push( $messages, __( 'Domain Name can not be empty', 'post-smtp' ) . '.' );
|
||||
$this->setNotConfiguredAndReady();
|
||||
}
|
||||
|
||||
if ( ! $this->isSenderConfigured() ) {
|
||||
array_push( $messages, __( 'Message From Address can not be empty', 'post-smtp' ) . '.' );
|
||||
$this->setNotConfiguredAndReady();
|
||||
}
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanModuleTransport::getConfigurationBid()
|
||||
*/
|
||||
public function getConfigurationBid( PostmanWizardSocket $hostData, $userAuthOverride, $originalSmtpServer ) {
|
||||
$recommendation = array();
|
||||
$recommendation ['priority'] = 0;
|
||||
$recommendation ['transport'] = self::SLUG;
|
||||
$recommendation ['hostname'] = null; // scribe looks this
|
||||
$recommendation ['label'] = $this->getName();
|
||||
$recommendation['logo_url'] = $this->getLogoURL();
|
||||
|
||||
if ( $hostData->hostname == $this->getHostname() && $hostData->port == self::PORT ) {
|
||||
$recommendation ['priority'] = self::PRIORITY;
|
||||
/* translators: where variables are (1) transport name (2) host and (3) port */
|
||||
$recommendation ['message'] = sprintf( __( ('Postman recommends the %1$s to host %2$s on port %3$d.') ), $this->getName(), $this->getHostname(), self::PORT );
|
||||
}
|
||||
return $recommendation;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mixed $hostname
|
||||
* @param mixed $response
|
||||
*/
|
||||
public function populateConfiguration( $hostname ) {
|
||||
$response = parent::populateConfiguration( $hostname );
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function createOverrideMenu( PostmanWizardSocket $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride ) {
|
||||
$overrideItem = parent::createOverrideMenu( $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride );
|
||||
// push the authentication options into the $overrideItem structure
|
||||
$overrideItem ['auth_items'] = array(
|
||||
array(
|
||||
'selected' => true,
|
||||
'name' => __( 'API Key', 'post-smtp' ),
|
||||
'value' => 'api_key',
|
||||
),
|
||||
);
|
||||
return $overrideItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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->addSettings();
|
||||
$this->registerStylesAndScripts();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* What follows in the code responsible for creating the Admin Settings page
|
||||
*/
|
||||
|
||||
/**
|
||||
*/
|
||||
public function addSettings() {
|
||||
// the Mailgun Auth section
|
||||
add_settings_section( PostmanMailgunTransport::MAILGUN_AUTH_SECTION, __( 'Authentication', 'post-smtp' ), array(
|
||||
$this,
|
||||
'printMailgunAuthSectionInfo',
|
||||
), PostmanMailgunTransport::MAILGUN_AUTH_OPTIONS );
|
||||
|
||||
add_settings_field( PostmanOptions::MAILGUN_API_KEY, __( 'API Key', 'post-smtp' ), array(
|
||||
$this,
|
||||
'mailgun_api_key_callback',
|
||||
), PostmanMailgunTransport::MAILGUN_AUTH_OPTIONS, PostmanMailgunTransport::MAILGUN_AUTH_SECTION );
|
||||
|
||||
add_settings_field( PostmanOptions::MAILGUN_DOMAIN_NAME, __( 'Domain Name', 'post-smtp' ), array(
|
||||
$this,
|
||||
'mailgun_domain_name_callback',
|
||||
), PostmanMailgunTransport::MAILGUN_AUTH_OPTIONS, PostmanMailgunTransport::MAILGUN_AUTH_SECTION );
|
||||
|
||||
add_settings_field( PostmanOptions::MAILGUN_REGION, __( 'Mailgun Europe Region?', 'post-smtp' ), array(
|
||||
$this,
|
||||
'mailgun_region_callback',
|
||||
), PostmanMailgunTransport::MAILGUN_AUTH_OPTIONS, PostmanMailgunTransport::MAILGUN_AUTH_SECTION );
|
||||
}
|
||||
public function printMailgunAuthSectionInfo() {
|
||||
/* Translators: Where (1) is the service URL and (2) is the service name and (3) is a api key URL */
|
||||
printf( '<p id="wizard_mailgun_auth_help">%s</p>', sprintf( __( 'Create an account at <a href="%1$s" target="_blank">%2$s</a> and enter <a href="%3$s" target="_blank">an API key</a> below.', 'post-smtp' ), 'https://mailgun.com', 'mailgun.com', 'https://app.mailgun.com/app/domains/' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function mailgun_api_key_callback() {
|
||||
printf( '<input type="password" autocomplete="off" id="mailgun_api_key" name="postman_options[mailgun_api_key]" value="%s" size="60" class="required ps-input ps-w-75" placeholder="%s"/>', null !== $this->options->getMailgunApiKey() ? esc_attr( PostmanUtils::obfuscatePassword( $this->options->getMailgunApiKey() ) ) : '', __( 'Required', 'post-smtp' ) );
|
||||
print '<input type="button" id="toggleMailgunApiKey" value="Show Password" class="button button-secondary" style="visibility:hidden" />';
|
||||
print '<p><span class="postman_input_description">Follow this link to get an API Key from Mailgun: <a target="_blank" href="https://app.mailgun.com/app/account/security/api_keys">Get a Private API Key.</a></span></p>';
|
||||
}
|
||||
|
||||
function mailgun_domain_name_callback() {
|
||||
printf( '<input type="text" autocomplete="off" id="mailgun_domain_name" name="postman_options[mailgun_domain_name]" value="%s" size="60" class="required ps-input ps-w-75" placeholder="%s"/>', null !== $this->options->getMailgunDomainName() ? esc_attr( $this->options->getMailgunDomainName() ) : '', __( 'Required', 'post-smtp' ) );
|
||||
print '<p><span class="postman_input_description"> Follow this link to get a Domain Name from Mailgun:<a target="_blank" href="https://app.mailgun.com/app/domains"> Get a Domain Name.</a></span></p>';
|
||||
}
|
||||
|
||||
function mailgun_region_callback() {
|
||||
$value = $this->options->getMailgunRegion();
|
||||
printf( '<input type="checkbox" id="mailgun_region" name="postman_options[mailgun_region]"%s />', null !== $value ? ' checked' : '' );
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function registerStylesAndScripts() {
|
||||
// register the stylesheet and javascript external resources
|
||||
$pluginData = apply_filters( 'postman_get_plugin_metadata', null );
|
||||
wp_register_script( 'postman_mailgun_script', plugins_url( 'Postman/Postman-Mail/postman_mailgun.js', $this->rootPluginFilenameAndPath ), array(
|
||||
PostmanViewController::JQUERY_SCRIPT,
|
||||
'jquery_validation',
|
||||
PostmanViewController::POSTMAN_SCRIPT,
|
||||
), $pluginData ['version'] );
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function enqueueScript() {
|
||||
wp_enqueue_script( 'postman_mailgun_script' );
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function printWizardAuthenticationStep() {
|
||||
print '<section class="wizard_mailgun">';
|
||||
$this->printMailgunAuthSectionInfo();
|
||||
printf( '<label for="api_key">%s</label>', __( 'API Key', 'post-smtp' ) );
|
||||
print '<br />';
|
||||
print $this->mailgun_api_key_callback();
|
||||
printf( '<label for="domain_name">%s</label>', __( 'Domain Name', 'post-smtp' ) );
|
||||
print '<br />';
|
||||
print $this->mailgun_domain_name_callback();
|
||||
print '<br />';
|
||||
printf( '<label for="mailgun_region">%s</label>', __( 'Mailgun Europe Region?', 'post-smtp' ) );
|
||||
print '<br />';
|
||||
print $this->mailgun_region_callback();
|
||||
print '</section>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Socket's logo
|
||||
*
|
||||
* @since 2.1
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getLogoURL() {
|
||||
|
||||
return POST_SMTP_ASSETS . "images/logos/mailgun.png";
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true, to prevent from errors because it's default Module Transport.
|
||||
*
|
||||
* @since 2.1.8
|
||||
* @version 1.0
|
||||
*/
|
||||
public function has_granted() {
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,276 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
if( !class_exists( 'PostmanMailjetMailEngine' ) ):
|
||||
|
||||
require 'Services/Mailjet/Handler.php';
|
||||
|
||||
class PostmanMailjetMailEngine implements PostmanMailEngine {
|
||||
|
||||
protected $logger;
|
||||
|
||||
private $transcript;
|
||||
|
||||
private $api_key;
|
||||
private $secret_key;
|
||||
|
||||
|
||||
/**
|
||||
* @since 2.7
|
||||
* @version 1.0
|
||||
*/
|
||||
public function __construct( $api_key, $secret_key ) {
|
||||
|
||||
$this->api_key = $api_key;
|
||||
$this->secret_key = $secret_key;
|
||||
|
||||
// create the logger
|
||||
$this->logger = new PostmanLogger( get_class( $this ) );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.7
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getTranscript() {
|
||||
return $this->transcript;
|
||||
}
|
||||
|
||||
private function addAttachmentsToMail( PostmanMessage $message ) {
|
||||
|
||||
$attachments = $message->getAttachments();
|
||||
if ( ! is_array( $attachments ) ) {
|
||||
// WordPress may a single filename or a newline-delimited string list of multiple filenames
|
||||
$attArray = explode( PHP_EOL, $attachments );
|
||||
} else {
|
||||
$attArray = $attachments;
|
||||
}
|
||||
// otherwise WordPress sends an array
|
||||
$attachments = array();
|
||||
foreach ( $attArray as $file ) {
|
||||
if ( ! empty( $file ) ) {
|
||||
$this->logger->debug( 'Adding attachment: ' . $file );
|
||||
|
||||
$file_name = basename( $file );
|
||||
$file_parts = explode( '.', $file_name );
|
||||
$file_type = wp_check_filetype( $file );
|
||||
$attachments[] = array(
|
||||
'content' => base64_encode( file_get_contents( $file ) ),
|
||||
'type' => $file_type['type'],
|
||||
'file_name' => $file_name,
|
||||
'disposition' => 'attachment',
|
||||
'id' => $file_parts[0],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $attachments;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.7
|
||||
* @version 1.0
|
||||
*/
|
||||
public function send( PostmanMessage $message ) {
|
||||
|
||||
$options = PostmanOptions::getInstance();
|
||||
|
||||
//Mailjet preparation
|
||||
if ( $this->logger->isDebug() ) {
|
||||
|
||||
$this->logger->debug( 'Creating Mailjet service with apiKey=' . $this->apiKey );
|
||||
|
||||
}
|
||||
|
||||
$mailjet = new PostmanMailjet( $this->api_key, $this->secret_key );
|
||||
$sender = $message->getFromAddress();
|
||||
$senderEmail = !empty( $sender->getEmail() ) ? $sender->getEmail() : $options->getMessageSenderEmail();
|
||||
$senderName = !empty( $sender->getName() ) ? $sender->getName() : $options->getMessageSenderName();
|
||||
$headers = array();
|
||||
|
||||
$sender->log( $this->logger, 'From' );
|
||||
|
||||
//Add FromEmail and Name
|
||||
$sendSmtpEmail['FromEmail'] = $senderEmail;
|
||||
$sendSmtpEmail['FromName'] = $senderName;
|
||||
|
||||
//Add subject
|
||||
$sendSmtpEmail['Subject'] = $message->getSubject();
|
||||
|
||||
|
||||
//add the To recipients
|
||||
$tos = array();
|
||||
foreach ( (array)$message->getToRecipients() as $key => $recipient ) {
|
||||
|
||||
$tos[] = !empty( $recipient->getName() ) ? $recipient->getName() . ' <' . $recipient->getEmail() . '>' : $recipient->getEmail();
|
||||
}
|
||||
|
||||
if( !empty( $tos ) ){
|
||||
|
||||
$sendSmtpEmail['To'] = $tos[0];
|
||||
|
||||
if( sizeof($tos)>1 ){
|
||||
|
||||
for( $i=1 ; $i<sizeof($tos) ; $i++ ){
|
||||
|
||||
$sendSmtpEmail['To'] = $sendSmtpEmail['To'] . ',' . $tos[$i];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//Add text part if any
|
||||
$textPart = $message->getBodyTextPart();
|
||||
if ( ! empty( $textPart ) ) {
|
||||
$this->logger->debug( 'Adding body as text' );
|
||||
$sendSmtpEmail['Text-part'] = $textPart;
|
||||
}
|
||||
|
||||
//Add html part if any
|
||||
$htmlPart = $message->getBodyHtmlPart();
|
||||
if ( ! empty( $htmlPart ) ) {
|
||||
$this->logger->debug( 'Adding body as html' );
|
||||
$sendSmtpEmail['Html-part'] = $htmlPart;
|
||||
}
|
||||
|
||||
// add the reply-to
|
||||
$get_reply_to = $message->getReplyTo();
|
||||
|
||||
$reply_to = '';
|
||||
|
||||
if ( !empty( $get_reply_to ) ) {
|
||||
|
||||
$reply_to = !empty( $get_reply_to->getName() ) ? $get_reply_to->getName() . ' <' . $get_reply_to->getEmail() . '>' : $get_reply_to->getEmail();
|
||||
|
||||
$headers['Reply-To'] = $reply_to;
|
||||
|
||||
}
|
||||
|
||||
// add the Postman signature - append it to whatever the user may have set
|
||||
if ( ! $options->isStealthModeEnabled() ) {
|
||||
$pluginData = apply_filters( 'postman_get_plugin_metadata', null );
|
||||
$headers['X-Mailer'] = sprintf( 'Postman SMTP %s for WordPress (%s)', $pluginData ['version'], 'https://wordpress.org/plugins/post-smtp/' );
|
||||
}
|
||||
|
||||
foreach ( ( array ) $message->getHeaders() as $header ) {
|
||||
$this->logger->debug( sprintf( 'Adding user header %s=%s', $header ['name'], $header ['content'] ) );
|
||||
$headers[$header['name']] = $header ['content'];
|
||||
}
|
||||
|
||||
// add the messageId
|
||||
$messageId = $message->getMessageId();
|
||||
if ( ! empty( $messageId ) ) {
|
||||
$headers['message-id'] = $messageId;
|
||||
}
|
||||
|
||||
$sendSmtpEmail['Headers'] = $headers;
|
||||
|
||||
// if the caller set a Content-Type header, use it
|
||||
$contentType = $message->getContentType();
|
||||
if ( ! empty( $contentType ) ) {
|
||||
$this->logger->debug( 'Some header keys are reserved. You may not include any of the following reserved headers: x-sg-id, x-sg-eid, received, dkim-signature, Content-Type, Content-Transfer-Encoding, To, From, Subject, Reply-To, CC, BCC.' );
|
||||
}
|
||||
|
||||
//Add CC
|
||||
$cc = array();
|
||||
|
||||
foreach ( ( array ) $message->getCcRecipients() as $recipient ) {
|
||||
|
||||
$cc[] = !empty( $recipient->getName() ) ? $recipient->getName() . '<' . $recipient->getEmail() .'>' : $recipient->getEmail() ;
|
||||
|
||||
}
|
||||
|
||||
if( !empty( $cc ) ){
|
||||
|
||||
$sendSmtpEmail['CC'] = $cc[0];
|
||||
|
||||
if( sizeof($cc)>1 ){
|
||||
|
||||
for( $i=1 ; $i<sizeof($cc) ; $i++ ){
|
||||
|
||||
$sendSmtpEmail['CC'] = $sendSmtpEmail['CC'] . ',' . $cc[$i];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//Add BCC
|
||||
$bcc = array();
|
||||
|
||||
foreach ( ( array ) $message->getBccRecipients() as $recipient ) {
|
||||
|
||||
$bcc[] = !empty( $recipient->getName() ) ? $recipient->getName() . '<' . $recipient->getEmail() .'>' : $recipient->getEmail() ;
|
||||
|
||||
}
|
||||
|
||||
if( !empty( $bcc ) ){
|
||||
|
||||
$sendSmtpEmail['Bcc'] = $bcc[0];
|
||||
|
||||
if( sizeof($bcc)>1 ){
|
||||
|
||||
for( $i=1 ; $i<sizeof($bcc) ; $i++ ){
|
||||
|
||||
$sendSmtpEmail['Bcc'] = $sendSmtpEmail['Bcc'] . ',' . $bcc[$i];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// add attachments
|
||||
$this->logger->debug( 'Adding attachments' );
|
||||
|
||||
$attachments = $this->addAttachmentsToMail( $message );
|
||||
|
||||
$email_attachments = array();
|
||||
|
||||
if( !empty( $attachments ) ) {
|
||||
|
||||
foreach ( $attachments as $index => $attachment ) {
|
||||
|
||||
$email_attachments[] = array(
|
||||
'Filename' => $attachment['file_name'],
|
||||
'Content-type' => $attachment['type'],
|
||||
'Content' => $attachment['content']
|
||||
);
|
||||
}
|
||||
|
||||
$sendSmtpEmail['Attachments'] = $email_attachments;
|
||||
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
// send the message
|
||||
if ( $this->logger->isDebug() ) {
|
||||
$this->logger->debug( 'Sending mail' );
|
||||
}
|
||||
|
||||
$response = $mailjet->send( $sendSmtpEmail );
|
||||
|
||||
$this->transcript = print_r( $response, true );
|
||||
$this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
|
||||
$this->transcript .= print_r( $sendSmtpEmail, true );
|
||||
$this->logger->debug( 'Transcript=' . $this->transcript );
|
||||
|
||||
} catch (Exception $e) {
|
||||
|
||||
$this->transcript = $e->getMessage();
|
||||
$this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
|
||||
$this->transcript .= print_r( $sendSmtpEmail, true );
|
||||
$this->logger->debug( 'Transcript=' . $this->transcript );
|
||||
|
||||
throw $e;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
endif;
|
||||
@@ -0,0 +1,345 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once 'PostmanModuleTransport.php';
|
||||
|
||||
/**
|
||||
* Postman Mailjet
|
||||
* @since 2.7
|
||||
* @version 1.0
|
||||
*/
|
||||
if( !class_exists( 'PostmanMailjetTransport' ) ):
|
||||
class PostmanMailjetTransport extends PostmanAbstractModuleTransport implements PostmanModuleTransport {
|
||||
|
||||
const SLUG = 'mailjet_api';
|
||||
const PORT = 587;
|
||||
const HOST = 'in-v3.mailjet.com';
|
||||
const PRIORITY = 52000;
|
||||
const MAILJET_AUTH_OPTIONS = 'postman_mailjet_auth_options';
|
||||
const MAILJET_AUTH_SECTION = 'postman_mailjet_auth_section';
|
||||
|
||||
/**
|
||||
* PostmanMailjetTransport constructor.
|
||||
* @param $rootPluginFilenameAndPath
|
||||
* @since 2.7
|
||||
* @version 1.0
|
||||
*/
|
||||
public function __construct( $rootPluginFilenameAndPath ) {
|
||||
|
||||
parent::__construct ( $rootPluginFilenameAndPath );
|
||||
|
||||
// add a hook on the plugins_loaded event
|
||||
add_action ( 'admin_init', array ( $this, 'on_admin_init' ) );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
* @since 2.7
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getPort() {
|
||||
return self::PORT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @since 2.7
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getSlug() {
|
||||
return self::SLUG;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @since 2.7
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getProtocol() {
|
||||
return 'https';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @since 2.7
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getHostname() {
|
||||
return self::HOST;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.7
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getConfigurationBid( PostmanWizardSocket $hostData, $userAuthOverride, $originalSmtpServer ) {
|
||||
|
||||
$recommendation = array();
|
||||
$recommendation ['priority'] = 0;
|
||||
$recommendation ['transport'] = self::SLUG;
|
||||
$recommendation ['hostname'] = null; // scribe looks this
|
||||
$recommendation ['label'] = $this->getName();
|
||||
$recommendation['logo_url'] = $this->getLogoURL();
|
||||
|
||||
if ($hostData->hostname == self::HOST && $hostData->port == self::PORT) {
|
||||
$recommendation ['priority'] = self::PRIORITY;
|
||||
/* translators: where variables are (1) transport name (2) host and (3) port */
|
||||
$recommendation ['message'] = sprintf ( __ ( ('Postman recommends the %1$s to host %2$s on port %3$d.') ), $this->getName(), self::HOST, self::PORT );
|
||||
}
|
||||
|
||||
return $recommendation;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.7
|
||||
* @version 1.0
|
||||
*/
|
||||
public function createMailEngine() {
|
||||
|
||||
$api_key = $this->options->getMailjetApiKey();
|
||||
$secret_key = $this->options->getMailjetSecretKey();
|
||||
require_once 'PostmanMailjetMailEngine.php';
|
||||
$engine = new PostmanMailjetMailEngine( $api_key,$secret_key );
|
||||
|
||||
return $engine;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.7
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getName() {
|
||||
|
||||
return __( 'Mailjet', 'post-smtp' );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.7
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getDeliveryDetails() {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PostmanWizardSocket $socket
|
||||
* @param $winningRecommendation
|
||||
* @param $userSocketOverride
|
||||
* @param $userAuthOverride
|
||||
* @return array
|
||||
* @since 2.7
|
||||
* @version 1.0
|
||||
*/
|
||||
public function createOverrideMenu( PostmanWizardSocket $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride ) {
|
||||
|
||||
$overrideItem = parent::createOverrideMenu ( $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride );
|
||||
|
||||
// push the authentication options into the $overrideItem structure
|
||||
$overrideItem ['auth_items'] = array (
|
||||
array (
|
||||
'selected' => true,
|
||||
'name' => __ ( 'API Key', 'post-smtp' ),
|
||||
'value' => 'api_key'
|
||||
)
|
||||
);
|
||||
|
||||
return $overrideItem;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.7
|
||||
* @version 1.0
|
||||
*/
|
||||
public function on_admin_init() {
|
||||
|
||||
if( PostmanUtils::isAdmin() ) {
|
||||
|
||||
$this->addSettings();
|
||||
$this->registerStylesAndScripts();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.7
|
||||
* @version 1.0
|
||||
*/
|
||||
public function addSettings()
|
||||
{
|
||||
|
||||
add_settings_section(
|
||||
self::MAILJET_AUTH_SECTION,
|
||||
__('Authentication', 'post-smtp'),
|
||||
array( $this, 'printMailjetAuthSectionInfo' ),
|
||||
self::MAILJET_AUTH_OPTIONS
|
||||
);
|
||||
|
||||
add_settings_field(
|
||||
PostmanOptions::MAILJET_API_KEY,
|
||||
__( 'API Key', 'post-smtp' ),
|
||||
array( $this, 'mailjet_api_key_callback' ),
|
||||
self::MAILJET_AUTH_OPTIONS,
|
||||
self::MAILJET_AUTH_SECTION
|
||||
);
|
||||
|
||||
add_settings_field(
|
||||
PostmanOptions::MAILJET_SECRET_KEY,
|
||||
__( 'Secret Key', 'post-smtp' ),
|
||||
array( $this, 'mailjet_secret_key_callback' ),
|
||||
self::MAILJET_AUTH_OPTIONS,
|
||||
self::MAILJET_AUTH_SECTION
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.7
|
||||
* @version 1.0
|
||||
*/
|
||||
public function printMailjetAuthSectionInfo() {
|
||||
|
||||
printf (
|
||||
'<p id="wizard_mailjet_auth_help">%s</p>', sprintf ( __ ( 'Create an account at <a href="%1$s" target="_blank">%2$s </a> and enter <a href="%3$s" target="_blank">an API key and Secret Key</a> below.', 'post-smtp' ),
|
||||
'https://app.mailjet.com', 'mailjet.com', 'https://app.mailjet.com/account/apikeys' )
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.7
|
||||
* @version 1.0
|
||||
*/
|
||||
public function mailjet_api_key_callback() {
|
||||
|
||||
printf ( '<input type="password" autocomplete="off" id="mailjet_api_key" name="postman_options[mailjet_api_key]" value="%s" size="60" class="required ps-input ps-w-75" placeholder="%s"/>', null !== $this->options->getMailjetApiKey() ? esc_attr ( PostmanUtils::obfuscatePassword ( $this->options->getMailjetApiKey()) ) : '', __ ( 'Required', 'post-smtp' ) );
|
||||
print ' <input type="button" id="toggleMailjetApiKey" value="Show Password" class="button button-secondary" style="visibility:hidden" />';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.7
|
||||
* @version 1.0
|
||||
*/
|
||||
public function mailjet_secret_key_callback(){
|
||||
|
||||
printf ( '<input type="password" autocomplete="off" id="mailjet_secret_key" name="postman_options[mailjet_secret_key]" value="%s" size="60" class="required ps-input ps-w-75" placeholder="%s"/>', null !== $this->options->getMailjetSecretKey() ? esc_attr ( PostmanUtils::obfuscatePassword ( $this->options->getMailjetSecretKey()) ) : '', __ ( 'Required', 'post-smtp' ) );
|
||||
print ' <input type="button" id="toggleMailjetSecretKey" value="Show Password" class="button button-secondary" style="visibility:hidden" />';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.7
|
||||
* @version 1.0
|
||||
*/
|
||||
public function registerStylesAndScripts() {
|
||||
|
||||
$pluginData = apply_filters( 'postman_get_plugin_metadata', null );
|
||||
|
||||
wp_register_script (
|
||||
'postman-mailjet',
|
||||
plugins_url ( 'Postman/Postman-Mail/postman-mailjet.js', $this->rootPluginFilenameAndPath ),
|
||||
array (
|
||||
PostmanViewController::JQUERY_SCRIPT,
|
||||
'jquery_validation',
|
||||
PostmanViewController::POSTMAN_SCRIPT
|
||||
),
|
||||
$pluginData['version']
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.7
|
||||
* @version 1.0
|
||||
*/
|
||||
public function enqueueScript() {
|
||||
|
||||
wp_enqueue_script( 'postman-mailjet' );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.7
|
||||
* @version 1.0
|
||||
*/
|
||||
public function printWizardAuthenticationStep() {
|
||||
print '<section class="wizard_mailjet">';
|
||||
$this->printMailjetAuthSectionInfo();
|
||||
printf ( '<label for="api_key">%s</label>', __ ( 'API Key', 'post-smtp' ) );
|
||||
print '<br />';
|
||||
print $this->mailjet_api_key_callback();
|
||||
printf ( '<label for="secret_key">%s</label>', __ ( 'Secret Key', 'post-smtp' ) );
|
||||
print '<br />';
|
||||
print $this->mailjet_secret_key_callback();
|
||||
print '</section>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Socket's logo
|
||||
*
|
||||
* @since 2.7
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getLogoURL() {
|
||||
|
||||
return POST_SMTP_ASSETS . "images/logos/Mailjet.png";
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true, to prevent from errors because it's default Module Transport.
|
||||
*
|
||||
* @since 2.7.8
|
||||
* @version 1.0
|
||||
*/
|
||||
public function has_granted() {
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanTransport::getMisconfigurationMessage()
|
||||
* @since 2.7.8
|
||||
* @version 1.0
|
||||
*/
|
||||
protected function validateTransportConfiguration() {
|
||||
$messages = parent::validateTransportConfiguration ();
|
||||
$apiKey = $this->options->getMailjetApiKey ();
|
||||
if (empty ( $apiKey )) {
|
||||
array_push ( $messages, __ ( 'API Key can not be empty', 'post-smtp' ) . '.' );
|
||||
$this->setNotConfiguredAndReady ();
|
||||
}
|
||||
if (! $this->isSenderConfigured ()) {
|
||||
array_push ( $messages, __ ( 'Message From Address can not be empty', 'post-smtp' ) . '.' );
|
||||
$this->setNotConfiguredAndReady ();
|
||||
}
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mixed $data
|
||||
* @since 2.7.8
|
||||
* @version 1.0
|
||||
*/
|
||||
public function prepareOptionsForExport($data) {
|
||||
$data = parent::prepareOptionsForExport ( $data );
|
||||
$data [PostmanOptions::MAILJET_API_KEY] = PostmanOptions::getInstance ()->getMailjetApiKey ();
|
||||
$data [PostmanOptions::MAILJET_SECRET_KEY] = PostmanOptions::getInstance ()->getMailjetSecretKey ();
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
endif;
|
||||
@@ -0,0 +1,277 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
if( !class_exists( 'PostmanMailtrapMailEngine' ) ):
|
||||
|
||||
require 'Services/Mailtrap/Handler.php';
|
||||
|
||||
class PostmanMailtrapMailEngine implements PostmanMailEngine {
|
||||
|
||||
protected $logger;
|
||||
|
||||
private $transcript;
|
||||
|
||||
private $api_key;
|
||||
|
||||
|
||||
/**
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function __construct( $api_key ) {
|
||||
|
||||
assert( !empty( $api_key ) );
|
||||
$this->api_key = $api_key;
|
||||
|
||||
// create the logger
|
||||
$this->logger = new PostmanLogger( get_class( $this ) );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getTranscript() {
|
||||
return $this->transcript;
|
||||
}
|
||||
|
||||
private function addAttachmentsToMail( PostmanMessage $message ) {
|
||||
|
||||
$attachments = $message->getAttachments();
|
||||
if ( ! is_array( $attachments ) ) {
|
||||
// WordPress may a single filename or a newline-delimited string list of multiple filenames
|
||||
$attArray = explode( PHP_EOL, $attachments );
|
||||
} else {
|
||||
$attArray = $attachments;
|
||||
}
|
||||
// otherwise WordPress sends an array
|
||||
$attachments = array();
|
||||
foreach ( $attArray as $file ) {
|
||||
if ( ! empty( $file ) ) {
|
||||
$this->logger->debug( 'Adding attachment: ' . $file );
|
||||
|
||||
$file_name = basename( $file );
|
||||
$file_type = wp_check_filetype( $file );
|
||||
$attachments[] = array(
|
||||
'content' => base64_encode( file_get_contents( $file ) ),
|
||||
'type' => $file_type['type'],
|
||||
'filename' => $file_name,
|
||||
'disposition' => 'attachment',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $attachments;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function send( PostmanMessage $message ) {
|
||||
|
||||
$options = PostmanOptions::getInstance();
|
||||
|
||||
if ( empty( $this->api_key ) ) {
|
||||
throw new Exception( 'Mailtrap API Key is not configured' );
|
||||
}
|
||||
|
||||
if ( $this->logger->isDebug() ) {
|
||||
$this->logger->debug( 'Creating Mailtrap service with apiKey=' . substr( $this->api_key, 0, 10 ) . '...' );
|
||||
}
|
||||
|
||||
$mailtrap = new PostmanMailtrap( $this->api_key);
|
||||
$sender = $message->getFromAddress();
|
||||
$senderEmail = !empty( $sender->getEmail() ) ? $sender->getEmail() : $options->getMessageSenderEmail();
|
||||
$senderName = !empty( $sender->getName() ) ? $sender->getName() : $options->getMessageSenderName();
|
||||
$headers = array();
|
||||
|
||||
$sender->log( $this->logger, 'From' );
|
||||
|
||||
// Prepare email payload
|
||||
$emailPayload = array();
|
||||
|
||||
// Set from address
|
||||
$emailPayload['from'] = array(
|
||||
'email' => $senderEmail
|
||||
);
|
||||
|
||||
if( !empty( $senderName ) ) {
|
||||
$emailPayload['from']['name'] = $senderName;
|
||||
}
|
||||
|
||||
$tos = array();
|
||||
$duplicates = array();
|
||||
|
||||
// add the to recipients
|
||||
foreach ( (array)$message->getToRecipients() as $key => $recipient ) {
|
||||
|
||||
if ( !in_array( $recipient->getEmail(), $duplicates ) ) {
|
||||
|
||||
$to = array(
|
||||
'email' => $recipient->getEmail()
|
||||
);
|
||||
|
||||
if( !empty( $recipient->getName() ) ) {
|
||||
$to['name'] = $recipient->getName();
|
||||
}
|
||||
|
||||
$tos[] = $to;
|
||||
$duplicates[] = $recipient->getEmail();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
$emailPayload['to'] = $tos;
|
||||
|
||||
$emailPayload['subject'] = $message->getSubject();
|
||||
|
||||
$textPart = $message->getBodyTextPart();
|
||||
if ( ! empty( $textPart ) ) {
|
||||
$this->logger->debug( 'Adding body as text' );
|
||||
$emailPayload['text'] = $textPart;
|
||||
}
|
||||
|
||||
$htmlPart = $message->getBodyHtmlPart();
|
||||
if ( ! empty( $htmlPart ) ) {
|
||||
$this->logger->debug( 'Adding body as html' );
|
||||
$emailPayload['html'] = $htmlPart;
|
||||
}
|
||||
|
||||
// add the reply-to
|
||||
$replyTo = $message->getReplyTo();
|
||||
// $replyTo is null or a PostmanEmailAddress object
|
||||
if ( isset( $replyTo ) ) {
|
||||
$emailPayload['reply_to'] = array(
|
||||
'email' => $replyTo->getEmail()
|
||||
);
|
||||
|
||||
if( !empty( $replyTo->getName() ) ) {
|
||||
$emailPayload['reply_to']['name'] = $replyTo->getName();
|
||||
}
|
||||
}
|
||||
|
||||
// add the Postman signature - append it to whatever the user may have set
|
||||
if ( ! $options->isStealthModeEnabled() ) {
|
||||
$pluginData = apply_filters( 'postman_get_plugin_metadata', null );
|
||||
$headers['X-Mailer'] = sprintf( 'Postman SMTP %s for WordPress (%s)', $pluginData ['version'], 'https://wordpress.org/plugins/post-smtp/' );
|
||||
}
|
||||
|
||||
foreach ( ( array ) $message->getHeaders() as $header ) {
|
||||
$this->logger->debug( sprintf( 'Adding user header %s=%s', $header ['name'], $header ['content'] ) );
|
||||
$headers[$header['name']] = $header ['content'];
|
||||
}
|
||||
|
||||
// add the messageId
|
||||
$messageId = $message->getMessageId();
|
||||
if ( ! empty( $messageId ) ) {
|
||||
$headers['message-id'] = $messageId;
|
||||
}
|
||||
|
||||
if( !empty( $headers ) ) {
|
||||
$emailPayload['headers'] = $headers;
|
||||
}
|
||||
|
||||
// if the caller set a Content-Type header, use it
|
||||
$contentType = $message->getContentType();
|
||||
if ( ! empty( $contentType ) ) {
|
||||
$this->logger->debug( 'Content-Type header is reserved and will be set automatically by Mailtrap API.' );
|
||||
}
|
||||
|
||||
$cc = array();
|
||||
$duplicates = array();
|
||||
foreach ( ( array ) $message->getCcRecipients() as $recipient ) {
|
||||
|
||||
if ( ! in_array( $recipient->getEmail(), $duplicates ) ) {
|
||||
|
||||
$recipient->log($this->logger, 'Cc');
|
||||
$ccItem = array(
|
||||
'email' => $recipient->getEmail()
|
||||
);
|
||||
|
||||
if( !empty( $recipient->getName() ) ) {
|
||||
$ccItem['name'] = $recipient->getName();
|
||||
}
|
||||
|
||||
$cc[] = $ccItem;
|
||||
$duplicates[] = $recipient->getEmail();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
if( !empty( $cc ) )
|
||||
$emailPayload['cc'] = $cc;
|
||||
|
||||
$bcc = array();
|
||||
$duplicates = array();
|
||||
foreach ( ( array ) $message->getBccRecipients() as $recipient ) {
|
||||
|
||||
if ( ! in_array( $recipient->getEmail(), $duplicates ) ) {
|
||||
|
||||
$recipient->log($this->logger, 'Bcc');
|
||||
$bccItem = array(
|
||||
'email' => $recipient->getEmail()
|
||||
);
|
||||
|
||||
if( !empty( $recipient->getName() ) ) {
|
||||
$bccItem['name'] = $recipient->getName();
|
||||
}
|
||||
|
||||
$bcc[] = $bccItem;
|
||||
$duplicates[] = $recipient->getEmail();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if( !empty( $bcc ) )
|
||||
$emailPayload['bcc'] = $bcc;
|
||||
|
||||
// add attachments
|
||||
$this->logger->debug( 'Adding attachments' );
|
||||
|
||||
$attachments = $this->addAttachmentsToMail( $message );
|
||||
|
||||
if( !empty( $attachments ) ) {
|
||||
$emailPayload['attachments'] = $attachments;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
// send the message
|
||||
if ( $this->logger->isDebug() ) {
|
||||
$this->logger->debug( 'Sending mail via Mailtrap API' );
|
||||
$this->logger->debug( 'Payload: ' . print_r( $emailPayload, true ) );
|
||||
}
|
||||
|
||||
$response = $mailtrap->send( $emailPayload );
|
||||
|
||||
if ( $this->logger->isDebug() ) {
|
||||
$this->logger->debug( 'Mailtrap API Response: ' . print_r( $response, true ) );
|
||||
}
|
||||
|
||||
$this->transcript = print_r( $response, true );
|
||||
$this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
|
||||
$this->transcript .= print_r( $emailPayload, true );
|
||||
$this->logger->debug( 'Transcript=' . $this->transcript );
|
||||
|
||||
} catch (Exception $e) {
|
||||
|
||||
$this->transcript = $e->getMessage();
|
||||
$this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
|
||||
$this->transcript .= print_r( $emailPayload, true );
|
||||
$this->logger->debug( 'Transcript=' . $this->transcript );
|
||||
$this->logger->error( 'Mailtrap send error: ' . $e->getMessage() );
|
||||
|
||||
throw $e;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
endif;
|
||||
@@ -0,0 +1,321 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once 'PostmanModuleTransport.php';
|
||||
|
||||
/**
|
||||
* Postman Mailtrap
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
if( !class_exists( 'PostmanMailtrapTransport' ) ):
|
||||
class PostmanMailtrapTransport extends PostmanAbstractModuleTransport implements PostmanModuleTransport {
|
||||
|
||||
const SLUG = 'mailtrap_api';
|
||||
const PORT = 587;
|
||||
const HOST = 'send.api.mailtrap.io';
|
||||
const PRIORITY = 50000;
|
||||
const MAILTRAP_AUTH_OPTIONS = 'postman_mailtrap_auth_options';
|
||||
const MAILTRAP_AUTH_SECTION = 'postman_mailtrap_auth_section';
|
||||
|
||||
/**
|
||||
* PostmanMailtrapTransport constructor.
|
||||
* @param $rootPluginFilenameAndPath
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function __construct( $rootPluginFilenameAndPath ) {
|
||||
|
||||
parent::__construct ( $rootPluginFilenameAndPath );
|
||||
|
||||
// add a hook on the plugins_loaded event
|
||||
add_action ( 'admin_init', array ( $this, 'on_admin_init' ) );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getPort() {
|
||||
return self::PORT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getSlug() {
|
||||
return self::SLUG;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getProtocol() {
|
||||
return 'https';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getHostname() {
|
||||
return self::HOST;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getConfigurationBid( PostmanWizardSocket $hostData, $userAuthOverride, $originalSmtpServer ) {
|
||||
|
||||
$recommendation = array();
|
||||
$recommendation ['priority'] = 0;
|
||||
$recommendation ['transport'] = self::SLUG;
|
||||
$recommendation ['hostname'] = null; // scribe looks this
|
||||
$recommendation ['label'] = $this->getName();
|
||||
$recommendation['logo_url'] = $this->getLogoURL();
|
||||
|
||||
if ($hostData->hostname == self::HOST && $hostData->port == self::PORT) {
|
||||
$recommendation ['priority'] = self::PRIORITY;
|
||||
/* translators: where variables are (1) transport name (2) host and (3) port */
|
||||
$recommendation ['message'] = sprintf ( __ ( ('Postman recommends the %1$s to host %2$s on port %3$d.') ), $this->getName(), self::HOST, self::PORT );
|
||||
}
|
||||
|
||||
return $recommendation;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function createMailEngine() {
|
||||
|
||||
$api_key = $this->options->getMailtrapApiKey();
|
||||
require_once 'PostmanMailtrapMailEngine.php';
|
||||
$engine = new PostmanMailtrapMailEngine( $api_key );
|
||||
|
||||
return $engine;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getName() {
|
||||
|
||||
return __( 'Mailtrap', 'post-smtp' );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getDeliveryDetails() {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PostmanWizardSocket $socket
|
||||
* @param $winningRecommendation
|
||||
* @param $userSocketOverride
|
||||
* @param $userAuthOverride
|
||||
* @return array
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function createOverrideMenu( PostmanWizardSocket $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride ) {
|
||||
|
||||
$overrideItem = parent::createOverrideMenu ( $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride );
|
||||
|
||||
// push the authentication options into the $overrideItem structure
|
||||
$overrideItem ['auth_items'] = array (
|
||||
array (
|
||||
'selected' => true,
|
||||
'name' => __ ( 'API Key', 'post-smtp' ),
|
||||
'value' => 'api_key'
|
||||
)
|
||||
);
|
||||
|
||||
return $overrideItem;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function on_admin_init() {
|
||||
|
||||
if( PostmanUtils::isAdmin() ) {
|
||||
|
||||
$this->addSettings();
|
||||
$this->registerStylesAndScripts();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function addSettings()
|
||||
{
|
||||
|
||||
add_settings_section(
|
||||
self::MAILTRAP_AUTH_SECTION,
|
||||
__('Authentication', 'post-smtp'),
|
||||
array( $this, 'printMailtrapAuthSectionInfo' ),
|
||||
self::MAILTRAP_AUTH_OPTIONS
|
||||
);
|
||||
|
||||
add_settings_field(
|
||||
PostmanOptions::MAILTRAP_API_KEY,
|
||||
__( 'API Token', 'post-smtp' ),
|
||||
array( $this, 'mailtrap_api_key_callback' ),
|
||||
self::MAILTRAP_AUTH_OPTIONS,
|
||||
self::MAILTRAP_AUTH_SECTION
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function printMailtrapAuthSectionInfo() {
|
||||
|
||||
printf (
|
||||
'<p id="wizard_mailtrap_auth_help">%s</p>', sprintf ( __ ( 'Create an account at <a href="%1$s" target="_blank">%2$s</a> and enter <a href="%3$s" target="_blank">an API token</a> below.', 'post-smtp' ),
|
||||
'https://mailtrap.io/', 'mailtrap.io', 'https://mailtrap.io/api-tokens' )
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function mailtrap_api_key_callback() {
|
||||
|
||||
printf ( '<input type="password" autocomplete="off" id="mailtrap_api_key" name="postman_options[mailtrap_api_key]" value="%s" size="60" class="required ps-input ps-w-75" placeholder="%s"/>', null !== $this->options->getMailtrapApiKey() ? esc_attr ( PostmanUtils::obfuscatePassword ( $this->options->getMailtrapApiKey() ) ) : '', __ ( 'Required', 'post-smtp' ) );
|
||||
print ' <input type="button" id="toggleMailtrapApiKey" value="Show Password" class="button button-secondary" style="visibility:hidden" />';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function registerStylesAndScripts() {
|
||||
|
||||
$pluginData = apply_filters( 'postman_get_plugin_metadata', null );
|
||||
|
||||
wp_register_script (
|
||||
'postman-mailtrap',
|
||||
plugins_url ( 'Postman/Postman-Mail/postman-mailtrap.js', $this->rootPluginFilenameAndPath ),
|
||||
array (
|
||||
PostmanViewController::JQUERY_SCRIPT,
|
||||
'jquery_validation',
|
||||
PostmanViewController::POSTMAN_SCRIPT
|
||||
),
|
||||
$pluginData['version']
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function enqueueScript() {
|
||||
|
||||
wp_enqueue_script( 'postman-mailtrap' );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function printWizardAuthenticationStep() {
|
||||
print '<section class="wizard_mailtrap">';
|
||||
$this->printMailtrapAuthSectionInfo();
|
||||
printf ( '<label for="api_key">%s</label>', __ ( 'API Token', 'post-smtp' ) );
|
||||
print '<br />';
|
||||
print $this->mailtrap_api_key_callback();
|
||||
print '</section>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Socket's logo
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getLogoURL() {
|
||||
|
||||
return POST_SMTP_ASSETS . "images/logos/mailtrap.png";
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true, to prevent from errors because it's default Module Transport.
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function has_granted() {
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanTransport::getMisconfigurationMessage()
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
protected function validateTransportConfiguration() {
|
||||
$messages = parent::validateTransportConfiguration ();
|
||||
$apiKey = $this->options->getMailtrapApiKey ();
|
||||
if (empty ( $apiKey )) {
|
||||
array_push ( $messages, __ ( 'API Token can not be empty', 'post-smtp' ) . '.' );
|
||||
$this->setNotConfiguredAndReady ();
|
||||
}
|
||||
if (! $this->isSenderConfigured ()) {
|
||||
array_push ( $messages, __ ( 'Message From Address can not be empty', 'post-smtp' ) . '.' );
|
||||
$this->setNotConfiguredAndReady ();
|
||||
}
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mixed $data
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function prepareOptionsForExport($data) {
|
||||
$data = parent::prepareOptionsForExport ( $data );
|
||||
$data [PostmanOptions::MAILTRAP_API_KEY] = PostmanOptions::getInstance ()->getMailtrapApiKey ();
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
endif;
|
||||
@@ -0,0 +1,273 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'PostmanMandrillMailEngine' ) ) {
|
||||
|
||||
require_once 'Services/Mandrill/Handler.php';
|
||||
|
||||
/**
|
||||
* Sends mail with Mandrill API
|
||||
* https://mandrillapp.com/api/docs/messages.php.html
|
||||
*
|
||||
* @author jasonhendriks
|
||||
*/
|
||||
class PostmanMandrillMailEngine implements PostmanMailEngine {
|
||||
|
||||
// logger for all concrete classes - populate with setLogger($logger)
|
||||
protected $logger;
|
||||
|
||||
// the result
|
||||
private $transcript;
|
||||
|
||||
private $apiKey;
|
||||
private $mandrillMessage;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mixed $senderEmail
|
||||
* @param mixed $accessToken
|
||||
*/
|
||||
function __construct( $apiKey ) {
|
||||
assert( ! empty( $apiKey ) );
|
||||
$this->apiKey = $apiKey;
|
||||
|
||||
// create the logger
|
||||
$this->logger = new PostmanLogger( get_class( $this ) );
|
||||
|
||||
// create the Message
|
||||
$this->mandrillMessage = array(
|
||||
'to' => array(),
|
||||
'headers' => array(),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanSmtpEngine::send()
|
||||
*/
|
||||
public function send( PostmanMessage $message ) {
|
||||
|
||||
$mandrill = new PostmanMandrill( $this->apiKey );
|
||||
$this->get_email_body( $message );
|
||||
|
||||
$result = array();
|
||||
try {
|
||||
|
||||
if ( $this->logger->isDebug() ) {
|
||||
$this->logger->debug( 'Creating Mandrill service with apiKey=' . $this->apiKey );
|
||||
}
|
||||
// send the message
|
||||
if ( $this->logger->isDebug() ) {
|
||||
$this->logger->debug( 'Sending mail' );
|
||||
}
|
||||
|
||||
$request = array(
|
||||
'message' => $this->mandrillMessage,
|
||||
'key' => $this->apiKey
|
||||
);
|
||||
|
||||
$result = $mandrill->send( $request );
|
||||
|
||||
if ( $this->logger->isInfo() ) {
|
||||
$this->logger->info( sprintf( 'Message %d accepted for delivery', PostmanState::getInstance()->getSuccessfulDeliveries() + 1 ) );
|
||||
}
|
||||
|
||||
$response_body = json_decode( $result['body'] );
|
||||
$response_body = reset( $response_body );
|
||||
$email_status = $response_body->status;
|
||||
$is_sent = ( $email_status == 'queued' OR $email_status == 'sent' );
|
||||
|
||||
if ( ! $is_sent ) {
|
||||
|
||||
$e = "Error: " . $response_body->reject_reason;
|
||||
|
||||
$this->transcript = $e;
|
||||
$this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
|
||||
$this->transcript .= print_r( $result, true );
|
||||
|
||||
$this->logger->debug( 'Transcript=' . $this->transcript );
|
||||
|
||||
throw new Exception( $e );
|
||||
}
|
||||
$this->transcript = print_r( $result, true );
|
||||
$this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
|
||||
$this->transcript .= print_r( $this->mandrillMessage, true );
|
||||
} catch ( Exception $e ) {
|
||||
$this->transcript = $e->getMessage();
|
||||
$this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
|
||||
$this->transcript .= print_r( $this->mandrillMessage, true );
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
private function addHeader( $key, $value, $append = false ) {
|
||||
$this->logger->debug( 'Adding header: ' . $key . ' = ' . $value );
|
||||
$header = &$this->mandrillMessage ['headers'];
|
||||
if ( $append && ! empty( $header [ $key ] ) ) {
|
||||
$header [ $key ] = $header [ $key ] . ', ' . $value;
|
||||
} else {
|
||||
$header [ $key ] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add attachments to the message
|
||||
*
|
||||
* @param Postman_Zend_Mail $mail
|
||||
*/
|
||||
private function addAttachmentsToMail( PostmanMessage $message ) {
|
||||
$attachments = $message->getAttachments();
|
||||
if ( isset( $attachments ) ) {
|
||||
$this->mandrillMessage ['attachments'] = array();
|
||||
if ( ! is_array( $attachments ) ) {
|
||||
// WordPress may a single filename or a newline-delimited string list of multiple filenames
|
||||
$attArray = explode( PHP_EOL, $attachments );
|
||||
} else {
|
||||
$attArray = $attachments;
|
||||
}
|
||||
// otherwise WordPress sends an array
|
||||
foreach ( $attArray as $file ) {
|
||||
if ( ! empty( $file ) ) {
|
||||
$this->logger->debug( 'Adding attachment: ' . $file );
|
||||
$attachment = array(
|
||||
'type' => 'attachment',
|
||||
'name' => basename( $file ),
|
||||
'content' => base64_encode( file_get_contents( $file ) ),
|
||||
);
|
||||
array_push( $this->mandrillMessage ['attachments'], $attachment );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// return the SMTP session transcript
|
||||
public function getTranscript() {
|
||||
return $this->transcript;
|
||||
}
|
||||
|
||||
/**
|
||||
* get_email_body
|
||||
*
|
||||
* @param mixed $message
|
||||
* @return void
|
||||
*/
|
||||
private function get_email_body( $message ) {
|
||||
$options = PostmanOptions::getInstance();
|
||||
|
||||
// add the Postman signature - append it to whatever the user may have set
|
||||
if ( ! $options->isStealthModeEnabled() ) {
|
||||
$pluginData = apply_filters( 'postman_get_plugin_metadata', null );
|
||||
$this->addHeader( 'X-Mailer', sprintf( 'Postman SMTP %s for WordPress (%s)', $pluginData ['version'], 'https://wordpress.org/plugins/post-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'] ) );
|
||||
$this->addHeader( $header ['name'], $header ['content'], true );
|
||||
}
|
||||
|
||||
// if the caller set a Content-Type header, use it
|
||||
$contentType = $message->getContentType();
|
||||
if ( ! empty( $contentType ) ) {
|
||||
$this->logger->debug( 'Adding content-type ' . $contentType );
|
||||
$this->addHeader( 'Content-Type', $contentType );
|
||||
}
|
||||
|
||||
// add the From Header
|
||||
$sender = $message->getFromAddress();
|
||||
{
|
||||
$senderEmail = PostmanOptions::getInstance()->getMessageSenderEmail();
|
||||
$senderName = $sender->getName();
|
||||
assert( ! empty( $senderEmail ) );
|
||||
$this->mandrillMessage ['from_email'] = $senderEmail;
|
||||
if ( ! empty( $senderName ) ) {
|
||||
$this->mandrillMessage ['from_name'] = $senderName;
|
||||
}
|
||||
// now log it
|
||||
$sender->log( $this->logger, 'From' );
|
||||
}
|
||||
|
||||
// add the Sender Header, overriding what the user may have set
|
||||
$this->addHeader( 'Sender', $options->getEnvelopeSender() );
|
||||
|
||||
// add the to recipients
|
||||
foreach ( ( array ) $message->getToRecipients() as $recipient ) {
|
||||
$recipient->log( $this->logger, 'To' );
|
||||
$recipient = array(
|
||||
'email' => $recipient->getEmail(),
|
||||
'name' => $recipient->getName(),
|
||||
'type' => 'to',
|
||||
);
|
||||
array_push( $this->mandrillMessage ['to'], $recipient );
|
||||
}
|
||||
|
||||
// add the cc recipients
|
||||
foreach ( ( array ) $message->getCcRecipients() as $recipient ) {
|
||||
$recipient->log( $this->logger, 'Cc' );
|
||||
$recipient = array(
|
||||
'email' => $recipient->getEmail(),
|
||||
'name' => $recipient->getName(),
|
||||
'type' => 'cc',
|
||||
);
|
||||
array_push( $this->mandrillMessage ['to'], $recipient );
|
||||
}
|
||||
|
||||
// add the bcc recipients
|
||||
foreach ( ( array ) $message->getBccRecipients() as $recipient ) {
|
||||
$recipient->log( $this->logger, 'Bcc' );
|
||||
$recipient = array(
|
||||
'email' => $recipient->getEmail(),
|
||||
'name' => $recipient->getName(),
|
||||
'type' => 'bcc',
|
||||
);
|
||||
array_push( $this->mandrillMessage ['to'], $recipient );
|
||||
}
|
||||
|
||||
// add the reply-to
|
||||
$replyTo = $message->getReplyTo();
|
||||
// $replyTo is null or a PostmanEmailAddress object
|
||||
if ( isset( $replyTo ) ) {
|
||||
$this->addHeader( 'reply-to', $replyTo->format() );
|
||||
}
|
||||
|
||||
// add the date
|
||||
$date = $message->getDate();
|
||||
if ( ! empty( $date ) ) {
|
||||
$this->addHeader( 'date', $message->getDate() );
|
||||
}
|
||||
|
||||
// add the messageId
|
||||
$messageId = $message->getMessageId();
|
||||
if ( ! empty( $messageId ) ) {
|
||||
$this->addHeader( 'message-id', $messageId );
|
||||
}
|
||||
|
||||
// add the subject
|
||||
if ( null !== $message->getSubject() ) {
|
||||
$this->mandrillMessage ['subject'] = $message->getSubject();
|
||||
}
|
||||
|
||||
// add the message content
|
||||
{
|
||||
$textPart = $message->getBodyTextPart();
|
||||
if ( ! empty( $textPart ) ) {
|
||||
$this->logger->debug( 'Adding body as text' );
|
||||
$this->mandrillMessage ['text'] = $textPart;
|
||||
}
|
||||
$htmlPart = $message->getBodyHtmlPart();
|
||||
if ( ! empty( $htmlPart ) ) {
|
||||
$this->logger->debug( 'Adding body as html' );
|
||||
$this->mandrillMessage ['html'] = $htmlPart;
|
||||
}
|
||||
}
|
||||
|
||||
// add attachments
|
||||
$this->logger->debug( 'Adding attachments' );
|
||||
$this->addAttachmentsToMail( $message );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,306 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
require_once 'PostmanModuleTransport.php';
|
||||
/**
|
||||
* Postman Mandrill module
|
||||
*
|
||||
* @author jasonhendriks
|
||||
*
|
||||
*/
|
||||
class PostmanMandrillTransport extends PostmanAbstractModuleTransport implements PostmanModuleTransport {
|
||||
const SLUG = 'mandrill_api';
|
||||
const PORT = 443;
|
||||
const HOST = 'mandrillapp.com';
|
||||
const PRIORITY = 46000;
|
||||
const MANDRILL_AUTH_OPTIONS = 'postman_mandrill_auth_options';
|
||||
const MANDRILL_AUTH_SECTION = 'postman_mandrill_auth_section';
|
||||
public function __construct($rootPluginFilenameAndPath) {
|
||||
parent::__construct ( $rootPluginFilenameAndPath );
|
||||
|
||||
// add a hook on the plugins_loaded event
|
||||
add_action ( 'admin_init', array (
|
||||
$this,
|
||||
'on_admin_init'
|
||||
) );
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mixed $data
|
||||
*/
|
||||
public function prepareOptionsForExport($data) {
|
||||
$data = parent::prepareOptionsForExport ( $data );
|
||||
$data [PostmanOptions::MANDRILL_API_KEY] = PostmanOptions::getInstance ()->getMandrillApiKey ();
|
||||
return $data;
|
||||
}
|
||||
public function getProtocol() {
|
||||
return 'https';
|
||||
}
|
||||
|
||||
// this should be standard across all transports
|
||||
public function getSlug() {
|
||||
return self::SLUG;
|
||||
}
|
||||
public function getName() {
|
||||
return __ ( 'Mandrill API', 'post-smtp' );
|
||||
}
|
||||
/**
|
||||
* v0.2.1
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getHostname() {
|
||||
return self::HOST;
|
||||
}
|
||||
/**
|
||||
* v0.2.1
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getPort() {
|
||||
return self::PORT;
|
||||
}
|
||||
/**
|
||||
* v1.7.0
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTransportType() {
|
||||
return 'mandrill_api';
|
||||
}
|
||||
/**
|
||||
* v0.2.1
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAuthenticationType() {
|
||||
return '';
|
||||
}
|
||||
/**
|
||||
* v0.2.1
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getSecurityType() {
|
||||
return self::PROTOCOL;
|
||||
}
|
||||
/**
|
||||
* v0.2.1
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCredentialsId() {
|
||||
return $this->options->getClientId ();
|
||||
}
|
||||
/**
|
||||
* v0.2.1
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCredentialsSecret() {
|
||||
return $this->options->getClientSecret ();
|
||||
}
|
||||
public function isServiceProviderGoogle($hostname) {
|
||||
return false;
|
||||
}
|
||||
public function isServiceProviderMicrosoft($hostname) {
|
||||
return false;
|
||||
}
|
||||
public function isServiceProviderYahoo($hostname) {
|
||||
return false;
|
||||
}
|
||||
public function isOAuthUsed($authType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanModuleTransport::createMailEngine()
|
||||
*/
|
||||
public function createMailEngine() {
|
||||
$apiKey = $this->options->getMandrillApiKey ();
|
||||
require_once 'PostmanMandrillMailEngine.php';
|
||||
$engine = new PostmanMandrillMailEngine ( $apiKey );
|
||||
return $engine;
|
||||
}
|
||||
|
||||
/**
|
||||
* This short description of the Transport State shows on the Summary screens
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanModuleTransport::getDeliveryDetails()
|
||||
*/
|
||||
public function getDeliveryDetails() {
|
||||
/* translators: where (1) is the secure icon and (2) is the transport name */
|
||||
return sprintf ( __ ( 'Postman will send mail via the <b>%1$s %2$s</b>.', 'post-smtp' ), '🔐', $this->getName () );
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanAbstractModuleTransport::validateTransportConfiguration()
|
||||
*/
|
||||
protected function validateTransportConfiguration() {
|
||||
$messages = parent::validateTransportConfiguration ();
|
||||
$apiKey = $this->options->getMandrillApiKey ();
|
||||
if (empty ( $apiKey )) {
|
||||
array_push ( $messages, __ ( 'API Key can not be empty', 'post-smtp' ) . '.' );
|
||||
$this->setNotConfiguredAndReady ();
|
||||
}
|
||||
if (! $this->isSenderConfigured ()) {
|
||||
array_push ( $messages, __ ( 'Message From Address can not be empty', 'post-smtp' ) . '.' );
|
||||
$this->setNotConfiguredAndReady ();
|
||||
}
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mandrill API doesn't care what the hostname or guessed SMTP Server is; it runs it's port test no matter what
|
||||
*/
|
||||
public function getSocketsForSetupWizardToProbe($hostname, $smtpServerGuess) {
|
||||
$hosts = array (
|
||||
self::createSocketDefinition ( $this->getHostname (), $this->getPort () )
|
||||
);
|
||||
return $hosts;
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanModuleTransport::getConfigurationBid()
|
||||
*/
|
||||
public function getConfigurationBid(PostmanWizardSocket $hostData, $userAuthOverride, $originalSmtpServer) {
|
||||
$recommendation = array ();
|
||||
$recommendation ['priority'] = 0;
|
||||
$recommendation ['transport'] = self::SLUG;
|
||||
$recommendation ['hostname'] = null; // scribe looks this
|
||||
$recommendation ['label'] = $this->getName ();
|
||||
$recommendation['logo_url'] = $this->getLogoURL();
|
||||
|
||||
if ($hostData->hostname == self::HOST && $hostData->port == self::PORT) {
|
||||
$recommendation ['priority'] = self::PRIORITY;
|
||||
/* translators: where variables are (1) transport name (2) host and (3) port */
|
||||
$recommendation ['message'] = sprintf ( __ ( ('Postman recommends the %1$s to host %2$s on port %3$d.') ), $this->getName (), self::HOST, self::PORT );
|
||||
}
|
||||
return $recommendation;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function createOverrideMenu(PostmanWizardSocket $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride) {
|
||||
$overrideItem = parent::createOverrideMenu ( $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride );
|
||||
// push the authentication options into the $overrideItem structure
|
||||
$overrideItem ['auth_items'] = array (
|
||||
array (
|
||||
'selected' => true,
|
||||
'name' => __ ( 'API Key', 'post-smtp' ),
|
||||
'value' => 'api_key'
|
||||
)
|
||||
);
|
||||
return $overrideItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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->addSettings ();
|
||||
$this->registerStylesAndScripts ();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* What follows in the code responsible for creating the Admin Settings page
|
||||
*/
|
||||
|
||||
/**
|
||||
*/
|
||||
public function addSettings() {
|
||||
// the Mandrill Auth section
|
||||
add_settings_section ( PostmanMandrillTransport::MANDRILL_AUTH_SECTION, __ ( 'Authentication', 'post-smtp' ), array (
|
||||
$this,
|
||||
'printMandrillAuthSectionInfo'
|
||||
), PostmanMandrillTransport::MANDRILL_AUTH_OPTIONS );
|
||||
|
||||
add_settings_field ( PostmanOptions::MANDRILL_API_KEY, __ ( 'API Key', 'post-smtp' ), array (
|
||||
$this,
|
||||
'mandrill_api_key_callback'
|
||||
), PostmanMandrillTransport::MANDRILL_AUTH_OPTIONS, PostmanMandrillTransport::MANDRILL_AUTH_SECTION );
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function printMandrillAuthSectionInfo() {
|
||||
/* Translators: Where (1) is the service URL and (2) is the service name and (3) is a api key URL */
|
||||
printf ( '<p id="wizard_mandrill_auth_help">%s</p>', sprintf ( __ ( 'Create an account at <a href="%1$s" target="_blank">%2$s</a> and enter <a href="%3$s" target="_blank">an API key</a> below.', 'post-smtp' ), 'https://mandrillapp.com', 'Mandrillapp.com', 'https://mandrillapp.com/settings' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
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 ps-input ps-w-75" placeholder="%s"/>', null !== $this->options->getMandrillApiKey () ? esc_attr ( PostmanUtils::obfuscatePassword ( $this->options->getMandrillApiKey () ) ) : '', __ ( 'Required', 'post-smtp' ) );
|
||||
print ' <input type="button" id="toggleMandrillApiKey" value="Show Password" class="button button-secondary" style="visibility:hidden" />';
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function registerStylesAndScripts() {
|
||||
// register the stylesheet and javascript external resources
|
||||
$pluginData = apply_filters ( 'postman_get_plugin_metadata', null );
|
||||
wp_register_script ( 'postman_mandrill_script', plugins_url ( 'Postman/Postman-Mail/postman_mandrill.js', $this->rootPluginFilenameAndPath ), array (
|
||||
PostmanViewController::JQUERY_SCRIPT,
|
||||
'jquery_validation',
|
||||
PostmanViewController::POSTMAN_SCRIPT
|
||||
), $pluginData ['version'] );
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function enqueueScript() {
|
||||
wp_enqueue_script ( 'postman_mandrill_script' );
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function printWizardAuthenticationStep() {
|
||||
print '<section class="wizard_mandrill">';
|
||||
$this->printMandrillAuthSectionInfo ();
|
||||
printf ( '<label for="api_key">%s</label>', __ ( 'API Key', 'post-smtp' ) );
|
||||
print '<br />';
|
||||
print $this->mandrill_api_key_callback ();
|
||||
print '</section>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Socket's logo
|
||||
*
|
||||
* @since 2.1
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getLogoURL() {
|
||||
|
||||
return POST_SMTP_ASSETS . "images/logos/mandrill.png";
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true, to prevent from errors because it's default Module Transport.
|
||||
*
|
||||
* @since 2.1.8
|
||||
* @version 1.0
|
||||
*/
|
||||
public function has_granted() {
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,830 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'PostmanMessage' ) ) {
|
||||
|
||||
require_once 'PostmanEmailAddress.php';
|
||||
|
||||
/**
|
||||
* This class knows how to interface with Wordpress
|
||||
* including loading/saving to the database.
|
||||
*
|
||||
* The various Transports available:
|
||||
* http://framework.zend.com/manual/current/en/modules/zend.mail.smtp.options.html
|
||||
*
|
||||
* @author jasonhendriks
|
||||
*/
|
||||
class PostmanMessage {
|
||||
const EOL = "\r\n";
|
||||
|
||||
// logger for all concrete classes - populate with setLogger($logger)
|
||||
protected $logger;
|
||||
|
||||
// set by the caller
|
||||
private $from;
|
||||
private $replyTo;
|
||||
private $toRecipients;
|
||||
private $ccRecipients;
|
||||
private $bccRecipients;
|
||||
private $subject;
|
||||
private $body;
|
||||
private $bodyTextPart;
|
||||
private $bodyHtmlPart;
|
||||
private $headers;
|
||||
private $attachments;
|
||||
private $date;
|
||||
private $messageId;
|
||||
|
||||
// determined by the send() method
|
||||
private $isTextHtml;
|
||||
private $contentType = 'text/plain';
|
||||
private $charset;
|
||||
|
||||
private $boundary;
|
||||
|
||||
/**
|
||||
* No-argument constructor
|
||||
*/
|
||||
function __construct() {
|
||||
$this->logger = new PostmanLogger( get_class( $this ) );
|
||||
$this->headers = array();
|
||||
$this->toRecipients = array();
|
||||
$this->ccRecipients = array();
|
||||
$this->bccRecipients = array();
|
||||
}
|
||||
|
||||
function __get( $name ) {
|
||||
$message = __( '<code>%1$s</code> property of a <code>PostmanMessage</code> object is <strong>not supported</strong>. For now all of this class properties are private.', 'post-smtp' );
|
||||
|
||||
if ( WP_DEBUG ) {
|
||||
trigger_error( sprintf( $message, $name ) );
|
||||
}
|
||||
}
|
||||
|
||||
function __call($name, $args) {
|
||||
$class = new ReflectionClass(__CLASS__);
|
||||
$methods = $class->getMethods(ReflectionMethod::IS_PUBLIC );
|
||||
|
||||
$message = __( '<code>%1$s</code> method of a <code>PostmanMessage</code> object is <strong>not supported</strong>. Use one of the following methods <pre><code>%2$s</code></pre>', 'post-smtp' );
|
||||
|
||||
if ( WP_DEBUG ) {
|
||||
trigger_error( sprintf( $message, $name, print_r( $methods, true ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isBodyPartsEmpty() {
|
||||
return empty( $this->bodyTextPart ) && empty( $this->bodyHtmlPart );
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param PostmanModuleTransport $transport
|
||||
*/
|
||||
public function validate( PostmanModuleTransport $transport ) {
|
||||
if ( $transport->isEmailValidationSupported() ) {
|
||||
$this->internalValidate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create body parts based on content type
|
||||
* MyMail creates its own body parts
|
||||
*/
|
||||
public function createBodyParts() {
|
||||
|
||||
// modify the content-type to include the boundary
|
||||
if ( false !== stripos( $this->contentType, 'multipart' ) && ! empty( $this->boundary ) ) {
|
||||
// Lines in email are terminated by CRLF ("\r\n") according to RFC2821
|
||||
$this->contentType = sprintf( "%s;\r\n\t boundary=\"%s\"", $this->contentType, $this->getBoundary() );
|
||||
}
|
||||
|
||||
$body = $this->getBody();
|
||||
$contentType = $this->getContentType();
|
||||
// add the message content as either text or html
|
||||
if ( empty( $contentType ) || substr( $contentType, 0, 10 ) === 'text/plain' ) {
|
||||
$this->logger->debug( 'Creating text body part' );
|
||||
$this->setBodyTextPart( $body );
|
||||
} else if ( substr( $contentType, 0, 9 ) === 'text/html' ) {
|
||||
$this->logger->debug( 'Creating html body part' );
|
||||
$this->setBodyHtmlPart( $body );
|
||||
} else if ( substr( $contentType, 0, 21 ) === 'multipart/alternative' ) {
|
||||
$this->logger->debug( 'Adding body as multipart/alternative' );
|
||||
$arr = explode( PHP_EOL, $body );
|
||||
$textBody = '';
|
||||
$htmlBody = '';
|
||||
$mode = '';
|
||||
foreach ( $arr as $s ) {
|
||||
$this->logger->trace( 'mode: ' . $mode . ' bodyline: ' . $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' ) {
|
||||
$trim = trim( $s );
|
||||
if ( empty( $trim ) ) {
|
||||
$mode = 'textReading';
|
||||
}
|
||||
} else if ( $mode == 'foundHtml' ) {
|
||||
$trim = trim( $s );
|
||||
if ( empty( $trim ) ) {
|
||||
$mode = 'htmlReading';
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->setBodyHtmlPart( $htmlBody );
|
||||
$this->setBodyTextPart( $textBody );
|
||||
} else {
|
||||
$this->logger->error( 'Unknown content-type: ' . $contentType );
|
||||
$this->setBodyTextPart( $body );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 );
|
||||
}
|
||||
|
||||
if ( $options->is_fallback ) {
|
||||
$fallback_email = $options->getFallbackFromEmail();
|
||||
$this->logger->debug( sprintf( 'Fallback: Forced From email address: before=%s after=%s', $this->getFromAddress()->getEmail(), $fallback_email ) );
|
||||
$this->getFromAddress()->setEmail( $fallback_email );
|
||||
}
|
||||
|
||||
$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 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check all email headers for errors
|
||||
* Throw an exception if an error is found
|
||||
*/
|
||||
private function internalValidate() {
|
||||
// check the reply-to address for errors
|
||||
if ( isset( $this->replyTo ) ) {
|
||||
$this->getReplyTo()->validate( 'Reply-To' );
|
||||
}
|
||||
|
||||
// check the from address for errors
|
||||
$this->getFromAddress()->validate( 'From' );
|
||||
|
||||
// validate the To recipients
|
||||
foreach ( ( array ) $this->getToRecipients() as $toRecipient ) {
|
||||
$toRecipient->validate( 'To' );
|
||||
}
|
||||
|
||||
// validate the Cc recipients
|
||||
foreach ( ( array ) $this->getCcRecipients() as $ccRecipient ) {
|
||||
$ccRecipient->validate( 'Cc' );
|
||||
}
|
||||
|
||||
// validate the Bcc recipients
|
||||
foreach ( ( array ) $this->getBccRecipients() as $bccRecipient ) {
|
||||
$bccRecipient->validate( 'Bcc' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return PostmanEmailAddress
|
||||
*/
|
||||
public function getFromAddress() {
|
||||
return $this->from;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the charset, checking first the WordPress bloginfo, then the header, then the wp_mail_charset filter.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCharset() {
|
||||
return $this->charset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the charset
|
||||
*
|
||||
* @param mixed $charset
|
||||
*/
|
||||
public function setCharset( $charset ) {
|
||||
$this->charset = $charset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the content type, checking first the header, then the wp_mail_content_type filter
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getContentType() {
|
||||
return $this->contentType;
|
||||
}
|
||||
public function setContentType( $contentType ) {
|
||||
$this->contentType = $contentType;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param mixed $recipients
|
||||
* Array or comma-separated list of email addresses to send message.
|
||||
* @throws Exception
|
||||
*/
|
||||
public function addTo( $to ) {
|
||||
$this->addRecipients( $this->toRecipients, $to );
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param mixed $recipients
|
||||
* Array or comma-separated list of email addresses to send message.
|
||||
* @throws Exception
|
||||
*/
|
||||
public function addCc( $cc ) {
|
||||
$this->addRecipients( $this->ccRecipients, $cc );
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param mixed $recipients
|
||||
* Array or comma-separated list of email addresses to send message.
|
||||
* @throws Exception
|
||||
*/
|
||||
public function addBcc( $bcc ) {
|
||||
$this->addRecipients( $this->bccRecipients, $bcc );
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param mixed $recipients
|
||||
* Array or comma-separated list of email addresses to send message.
|
||||
* @throws Exception
|
||||
*/
|
||||
private function addRecipients( &$recipientList, $recipients ) {
|
||||
if ( ! empty( $recipients ) ) {
|
||||
$recipients = PostmanEmailAddress::convertToArray( $recipients );
|
||||
foreach ( $recipients as $recipient ) {
|
||||
if ( ! empty( $recipient ) ) {
|
||||
$this->logger->debug( sprintf( 'User added recipient: "%s"', $recipient ) );
|
||||
array_push( $recipientList, new PostmanEmailAddress( $recipient ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For the string version, each header line (beginning with From:, Cc:, etc.) is delimited with a newline ("\r\n")
|
||||
*/
|
||||
public function addHeaders( $headers ) {
|
||||
if ( ! is_array( $headers ) ) {
|
||||
// WordPress may send a string where "each header line (beginning with From:, Cc:, etc.) is delimited with a newline ("\r\n") (advanced)"
|
||||
// this converts that string to an array
|
||||
$headers = empty( $headers ) ? explode( "\n", str_replace( "\r\n", "\n", '' ) ) : explode( "\n", str_replace( "\r\n", "\n", $headers ) );
|
||||
// $headers = explode ( PHP_EOL, $headers );
|
||||
}
|
||||
// otherwise WordPress sends an array
|
||||
foreach ( $headers as $header ) {
|
||||
if ( ! empty( $header ) ) {
|
||||
// boundary may be in a header line, but it's not a header
|
||||
// eg. boundary="----=_NextPart_DC7E1BB5...
|
||||
if ( strpos( $header, ':' ) === false ) {
|
||||
if ( false !== stripos( $header, 'boundary=' ) ) {
|
||||
$parts = preg_split( '/boundary=/i', trim( $header ) );
|
||||
$this->boundary = trim( str_replace( array(
|
||||
"'",
|
||||
'"',
|
||||
), '', $parts [1] ) );
|
||||
$this->logger->debug( sprintf( 'Processing special boundary header \'%s\'', $this->getBoundary() ) );
|
||||
} else {
|
||||
$this->logger->debug( sprintf( 'Ignoring broken header \'%s\'', $header ) );
|
||||
}
|
||||
continue;
|
||||
}
|
||||
list ( $name, $content ) = explode( ':', trim( $header ), 2 );
|
||||
$this->processHeader( $name, $content );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the headers that were processed in processHeaders()
|
||||
* Zend requires that several headers are specially handled.
|
||||
*
|
||||
* @param mixed $name
|
||||
* @param mixed $value
|
||||
* @param Postman_Zend_Mail $mail
|
||||
*/
|
||||
private function processHeader( $name, $content ) {
|
||||
$name = trim( $name );
|
||||
$content = trim( $content );
|
||||
switch ( strtolower( $name ) ) {
|
||||
case 'content-type' :
|
||||
$this->logProcessHeader( 'Content-Type', $name, $content );
|
||||
if ( strpos( $content, ';' ) !== false ) {
|
||||
list ( $type, $charset ) = explode( ';', $content );
|
||||
$this->setContentType( trim( $type ) );
|
||||
if ( false !== stripos( $charset, 'charset=' ) ) {
|
||||
$charset = trim( str_replace( array(
|
||||
'charset=',
|
||||
'"',
|
||||
), '', $charset ) );
|
||||
} elseif ( false !== stripos( $charset, 'boundary=' ) ) {
|
||||
$this->boundary = trim( str_replace( array(
|
||||
'BOUNDARY=',
|
||||
'boundary=',
|
||||
'"',
|
||||
), '', $charset ) );
|
||||
$charset = '';
|
||||
}
|
||||
if ( ! empty( $charset ) ) {
|
||||
$this->setCharset( $charset );
|
||||
}
|
||||
} else {
|
||||
$this->setContentType( trim( $content ) );
|
||||
}
|
||||
break;
|
||||
case 'to' :
|
||||
$this->logProcessHeader( 'To', $name, $content );
|
||||
$this->addTo( $content );
|
||||
break;
|
||||
case 'cc' :
|
||||
$this->logProcessHeader( 'Cc', $name, $content );
|
||||
$this->addCc( $content );
|
||||
break;
|
||||
case 'bcc' :
|
||||
$this->logProcessHeader( 'Bcc', $name, $content );
|
||||
$this->addBcc( $content );
|
||||
break;
|
||||
case 'from' :
|
||||
$this->logProcessHeader( 'From', $name, $content );
|
||||
$this->setFrom( $content );
|
||||
break;
|
||||
case 'subject' :
|
||||
$this->logProcessHeader( 'Subject', $name, $content );
|
||||
$this->setSubject( $content );
|
||||
break;
|
||||
case 'reply-to' :
|
||||
$this->logProcessHeader( 'Reply-To', $name, $content );
|
||||
$pattern = '/[a-z0-9_\-\+\.]+@[a-z0-9\-]+\.([a-z]{2,4})(?:\.[a-z]{2})?/i';
|
||||
preg_match_all($pattern, $content, $matches);
|
||||
|
||||
if ( isset( $matches[0] ) && isset( $matches[0][0] ) && filter_var( $matches[0][0], FILTER_VALIDATE_EMAIL ) ) {
|
||||
$this->setReplyTo( $content );
|
||||
}
|
||||
|
||||
break;
|
||||
case 'sender' :
|
||||
$this->logProcessHeader( 'Sender', $name, $content );
|
||||
$this->logger->warn( sprintf( 'Ignoring Sender header \'%s\'', $content ) );
|
||||
break;
|
||||
case 'return-path' :
|
||||
$this->logProcessHeader( 'Return-Path', $name, $content );
|
||||
$this->logger->warn( sprintf( 'Ignoring Return-Path header \'%s\'', $content ) );
|
||||
break;
|
||||
case 'date' :
|
||||
$this->logProcessHeader( 'Date', $name, $content );
|
||||
$this->setDate( $content );
|
||||
break;
|
||||
case 'message-id' :
|
||||
$this->logProcessHeader( 'Message-Id', $name, $content );
|
||||
$this->setMessageId( $content );
|
||||
break;
|
||||
default :
|
||||
// Add it to our grand headers array
|
||||
$this->logProcessHeader( 'other', $name, $content );
|
||||
array_push( $this->headers, array(
|
||||
'name' => $name,
|
||||
'content' => $content,
|
||||
) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mixed $desc
|
||||
* @param mixed $name
|
||||
* @param mixed $content
|
||||
*/
|
||||
private function logProcessHeader( $desc, $name, $content ) {
|
||||
$this->logger->debug( 'Processing ' . $desc . ' Header - ' . $name . ': ' . $content );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add attachments to the message
|
||||
*
|
||||
* @param Postman_Zend_Mail $mail
|
||||
*/
|
||||
public function addAttachmentsToMail( Postman_Zend_Mail $mail ) {
|
||||
$attachments = $this->attachments;
|
||||
if ( ! is_array( $attachments ) ) {
|
||||
// WordPress may a single filename or a newline-delimited string list of multiple filenames
|
||||
$attArray = explode( PHP_EOL, $attachments );
|
||||
} else {
|
||||
$attArray = $attachments;
|
||||
}
|
||||
// otherwise WordPress sends an array
|
||||
foreach ( $attArray as $file ) {
|
||||
if ( ! empty( $file ) ) {
|
||||
$this->logger->debug( 'Adding attachment: ' . $file );
|
||||
$at = new Postman_Zend_Mime_Part( file_get_contents( $file ) );
|
||||
// $at->type = 'image/gif';
|
||||
$at->disposition = Postman_Zend_Mime::DISPOSITION_ATTACHMENT;
|
||||
$at->encoding = Postman_Zend_Mime::ENCODING_BASE64;
|
||||
$at->filename = basename( $file );
|
||||
$mail->addAttachment( $at );
|
||||
}
|
||||
}
|
||||
}
|
||||
function setBody( $body ) {
|
||||
$this->body = $body;
|
||||
}
|
||||
function setBodyTextPart( $bodyTextPart ) {
|
||||
$this->bodyTextPart = $bodyTextPart;
|
||||
}
|
||||
function setBodyHtmlPart( $bodyHtmlPart ) {
|
||||
$this->bodyHtmlPart = $bodyHtmlPart;
|
||||
}
|
||||
function setSubject( $subject ) {
|
||||
$this->subject = $subject;
|
||||
}
|
||||
function setAttachments( $attachments ) {
|
||||
$this->attachments = $attachments;
|
||||
}
|
||||
function setFrom( $email, $name = null ) {
|
||||
if ( ! empty( $email ) ) {
|
||||
$this->from = new PostmanEmailAddress( $email, $name );
|
||||
}
|
||||
}
|
||||
function setReplyTo( $replyTo ) {
|
||||
if ( ! empty( $replyTo ) ) {
|
||||
$this->replyTo = new PostmanEmailAddress( $replyTo );
|
||||
}
|
||||
}
|
||||
function setMessageId( $messageId ) {
|
||||
$this->messageId = $messageId;
|
||||
}
|
||||
function setDate( $date ) {
|
||||
$this->date = $date;
|
||||
}
|
||||
|
||||
// return the headers
|
||||
public function getHeaders() {
|
||||
return $this->headers;
|
||||
}
|
||||
public function getBoundary() {
|
||||
return $this->boundary;
|
||||
}
|
||||
public function getToRecipients() {
|
||||
return $this->toRecipients;
|
||||
}
|
||||
public function getCcRecipients() {
|
||||
return $this->ccRecipients;
|
||||
}
|
||||
public function getBccRecipients() {
|
||||
return $this->bccRecipients;
|
||||
}
|
||||
public function getReplyTo() {
|
||||
return $this->replyTo;
|
||||
}
|
||||
public function getDate() {
|
||||
return $this->date;
|
||||
}
|
||||
public function getMessageId() {
|
||||
return $this->messageId;
|
||||
}
|
||||
public function getSubject() {
|
||||
return $this->subject;
|
||||
}
|
||||
public function getBody() {
|
||||
return $this->body;
|
||||
}
|
||||
public function getBodyTextPart() {
|
||||
return $this->bodyTextPart;
|
||||
}
|
||||
public function getBodyHtmlPart() {
|
||||
return $this->bodyHtmlPart;
|
||||
}
|
||||
public function getAttachments() {
|
||||
return $this->attachments;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo
|
||||
* is this right? maybe extending the phpmailer class insted?
|
||||
*/
|
||||
|
||||
/**
|
||||
* Add an embedded (inline) attachment from a file.
|
||||
* This can include images, sounds, and just about any other document type.
|
||||
* These differ from 'regular' attachments in that they are intended to be
|
||||
* displayed inline with the message, not just attached for download.
|
||||
* This is used in HTML messages that embed the images
|
||||
* the HTML refers to using the $cid value.
|
||||
* Never use a user-supplied path to a file!
|
||||
* @param string $path Path to the attachment.
|
||||
* @param string $cid Content ID of the attachment; Use this to reference
|
||||
* the content when using an embedded image in HTML.
|
||||
* @param string $name Overrides the attachment name.
|
||||
* @param string $encoding File encoding (see $Encoding).
|
||||
* @param string $type File MIME type.
|
||||
* @param string $disposition Disposition to use
|
||||
* @return boolean True on successfully adding an attachment
|
||||
*/
|
||||
public function addEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = '', $disposition = 'inline') {
|
||||
if (!@is_file($path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If a MIME type is not specified, try to work it out from the file name
|
||||
if ($type == '') {
|
||||
$type = self::filenameToType($path);
|
||||
}
|
||||
|
||||
$filename = basename($path);
|
||||
if ($name == '') {
|
||||
$name = $filename;
|
||||
}
|
||||
|
||||
// Append to $attachment array
|
||||
$this->attachments[] = array(
|
||||
0 => $path,
|
||||
1 => $filename,
|
||||
2 => $name,
|
||||
3 => $encoding,
|
||||
4 => $type,
|
||||
5 => false, // isStringAttachment
|
||||
6 => $disposition,
|
||||
7 => $cid
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the MIME type for a file extension.
|
||||
* @param string $ext File extension
|
||||
* @access public
|
||||
* @return string MIME type of file.
|
||||
* @static
|
||||
*/
|
||||
public static function _mime_types($ext = '')
|
||||
{
|
||||
$mimes = array(
|
||||
'xl' => 'application/excel',
|
||||
'js' => 'application/javascript',
|
||||
'hqx' => 'application/mac-binhex40',
|
||||
'cpt' => 'application/mac-compactpro',
|
||||
'bin' => 'application/macbinary',
|
||||
'doc' => 'application/msword',
|
||||
'word' => 'application/msword',
|
||||
'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
|
||||
'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template',
|
||||
'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
|
||||
'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
||||
'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
|
||||
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
|
||||
'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12',
|
||||
'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
|
||||
'class' => 'application/octet-stream',
|
||||
'dll' => 'application/octet-stream',
|
||||
'dms' => 'application/octet-stream',
|
||||
'exe' => 'application/octet-stream',
|
||||
'lha' => 'application/octet-stream',
|
||||
'lzh' => 'application/octet-stream',
|
||||
'psd' => 'application/octet-stream',
|
||||
'sea' => 'application/octet-stream',
|
||||
'so' => 'application/octet-stream',
|
||||
'oda' => 'application/oda',
|
||||
'pdf' => 'application/pdf',
|
||||
'ai' => 'application/postscript',
|
||||
'eps' => 'application/postscript',
|
||||
'ps' => 'application/postscript',
|
||||
'smi' => 'application/smil',
|
||||
'smil' => 'application/smil',
|
||||
'mif' => 'application/vnd.mif',
|
||||
'xls' => 'application/vnd.ms-excel',
|
||||
'ppt' => 'application/vnd.ms-powerpoint',
|
||||
'wbxml' => 'application/vnd.wap.wbxml',
|
||||
'wmlc' => 'application/vnd.wap.wmlc',
|
||||
'dcr' => 'application/x-director',
|
||||
'dir' => 'application/x-director',
|
||||
'dxr' => 'application/x-director',
|
||||
'dvi' => 'application/x-dvi',
|
||||
'gtar' => 'application/x-gtar',
|
||||
'php3' => 'application/x-httpd-php',
|
||||
'php4' => 'application/x-httpd-php',
|
||||
'php' => 'application/x-httpd-php',
|
||||
'phtml' => 'application/x-httpd-php',
|
||||
'phps' => 'application/x-httpd-php-source',
|
||||
'swf' => 'application/x-shockwave-flash',
|
||||
'sit' => 'application/x-stuffit',
|
||||
'tar' => 'application/x-tar',
|
||||
'tgz' => 'application/x-tar',
|
||||
'xht' => 'application/xhtml+xml',
|
||||
'xhtml' => 'application/xhtml+xml',
|
||||
'zip' => 'application/zip',
|
||||
'mid' => 'audio/midi',
|
||||
'midi' => 'audio/midi',
|
||||
'mp2' => 'audio/mpeg',
|
||||
'mp3' => 'audio/mpeg',
|
||||
'mpga' => 'audio/mpeg',
|
||||
'aif' => 'audio/x-aiff',
|
||||
'aifc' => 'audio/x-aiff',
|
||||
'aiff' => 'audio/x-aiff',
|
||||
'ram' => 'audio/x-pn-realaudio',
|
||||
'rm' => 'audio/x-pn-realaudio',
|
||||
'rpm' => 'audio/x-pn-realaudio-plugin',
|
||||
'ra' => 'audio/x-realaudio',
|
||||
'wav' => 'audio/x-wav',
|
||||
'bmp' => 'image/bmp',
|
||||
'gif' => 'image/gif',
|
||||
'jpeg' => 'image/jpeg',
|
||||
'jpe' => 'image/jpeg',
|
||||
'jpg' => 'image/jpeg',
|
||||
'png' => 'image/png',
|
||||
'tiff' => 'image/tiff',
|
||||
'tif' => 'image/tiff',
|
||||
'eml' => 'message/rfc822',
|
||||
'css' => 'text/css',
|
||||
'html' => 'text/html',
|
||||
'htm' => 'text/html',
|
||||
'shtml' => 'text/html',
|
||||
'log' => 'text/plain',
|
||||
'text' => 'text/plain',
|
||||
'txt' => 'text/plain',
|
||||
'rtx' => 'text/richtext',
|
||||
'rtf' => 'text/rtf',
|
||||
'vcf' => 'text/vcard',
|
||||
'vcard' => 'text/vcard',
|
||||
'xml' => 'text/xml',
|
||||
'xsl' => 'text/xml',
|
||||
'mpeg' => 'video/mpeg',
|
||||
'mpe' => 'video/mpeg',
|
||||
'mpg' => 'video/mpeg',
|
||||
'mov' => 'video/quicktime',
|
||||
'qt' => 'video/quicktime',
|
||||
'rv' => 'video/vnd.rn-realvideo',
|
||||
'avi' => 'video/x-msvideo',
|
||||
'movie' => 'video/x-sgi-movie'
|
||||
);
|
||||
if (array_key_exists(strtolower($ext), $mimes)) {
|
||||
return $mimes[strtolower($ext)];
|
||||
}
|
||||
return 'application/octet-stream';
|
||||
}
|
||||
|
||||
/**
|
||||
* Map a file name to a MIME type.
|
||||
* Defaults to 'application/octet-stream', i.e.. arbitrary binary data.
|
||||
* @param string $filename A file name or full path, does not need to exist as a file
|
||||
* @return string
|
||||
* @static
|
||||
*/
|
||||
public static function filenameToType($filename)
|
||||
{
|
||||
// In case the path is a URL, strip any query string before getting extension
|
||||
$qpos = strpos($filename, '?');
|
||||
if (false !== $qpos) {
|
||||
$filename = substr($filename, 0, $qpos);
|
||||
}
|
||||
$pathinfo = self::mb_pathinfo($filename);
|
||||
return self::_mime_types($pathinfo['extension']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Multi-byte-safe pathinfo replacement.
|
||||
* Drop-in replacement for pathinfo(), but multibyte-safe, cross-platform-safe, old-version-safe.
|
||||
* Works similarly to the one in PHP >= 5.2.0
|
||||
* @link http://www.php.net/manual/en/function.pathinfo.php#107461
|
||||
* @param string $path A filename or path, does not need to exist as a file
|
||||
* @param integer|string $options Either a PATHINFO_* constant,
|
||||
* or a string name to return only the specified piece, allows 'filename' to work on PHP < 5.2
|
||||
* @return string|array
|
||||
* @static
|
||||
*/
|
||||
public static function mb_pathinfo($path, $options = null)
|
||||
{
|
||||
$ret = array('dirname' => '', 'basename' => '', 'extension' => '', 'filename' => '');
|
||||
$pathinfo = array();
|
||||
if (preg_match('%^(.*?)[\\\\/]*(([^/\\\\]*?)(\.([^\.\\\\/]+?)|))[\\\\/\.]*$%im', $path, $pathinfo)) {
|
||||
if (array_key_exists(1, $pathinfo)) {
|
||||
$ret['dirname'] = $pathinfo[1];
|
||||
}
|
||||
if (array_key_exists(2, $pathinfo)) {
|
||||
$ret['basename'] = $pathinfo[2];
|
||||
}
|
||||
if (array_key_exists(5, $pathinfo)) {
|
||||
$ret['extension'] = $pathinfo[5];
|
||||
}
|
||||
if (array_key_exists(3, $pathinfo)) {
|
||||
$ret['filename'] = $pathinfo[3];
|
||||
}
|
||||
}
|
||||
switch ($options) {
|
||||
case PATHINFO_DIRNAME:
|
||||
case 'dirname':
|
||||
return $ret['dirname'];
|
||||
case PATHINFO_BASENAME:
|
||||
case 'basename':
|
||||
return $ret['basename'];
|
||||
case PATHINFO_EXTENSION:
|
||||
case 'extension':
|
||||
return $ret['extension'];
|
||||
case PATHINFO_FILENAME:
|
||||
case 'filename':
|
||||
return $ret['filename'];
|
||||
default:
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,813 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep the interface_exists check here for Postman Gmail API Extension users!
|
||||
*
|
||||
* @author jasonhendriks
|
||||
*/
|
||||
if (! interface_exists ( 'PostmanTransport' )) {
|
||||
interface PostmanTransport {
|
||||
public function isServiceProviderGoogle($hostname);
|
||||
public function isServiceProviderMicrosoft($hostname);
|
||||
public function isServiceProviderYahoo($hostname);
|
||||
// @deprecated
|
||||
public function isOAuthUsed($authType);
|
||||
public function isTranscriptSupported();
|
||||
public function getSlug();
|
||||
public function getName();
|
||||
// @deprecated
|
||||
public function createPostmanMailAuthenticator(PostmanOptions $options, PostmanOAuthToken $authToken);
|
||||
public function createZendMailTransport($fakeHostname, $fakeConfig);
|
||||
public function isConfigured(PostmanOptionsInterface $options, PostmanOAuthToken $token);
|
||||
public function isReady(PostmanOptionsInterface $options, PostmanOAuthToken $token);
|
||||
// @deprecated
|
||||
public function getMisconfigurationMessage(PostmanConfigTextHelper $scribe, PostmanOptionsInterface $options, PostmanOAuthToken $token);
|
||||
// @deprecated
|
||||
public function getConfigurationRecommendation($hostData);
|
||||
// @deprecated
|
||||
public function getHostsToTest($hostname);
|
||||
|
||||
/**
|
||||
* Get Socket's logo
|
||||
*
|
||||
* @since 2.1
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getLogoURL();
|
||||
}
|
||||
}
|
||||
interface PostmanModuleTransport extends PostmanTransport {
|
||||
const RAW_MESSAGE_FOLLOWS = '
|
||||
|
||||
--Raw message follows--
|
||||
|
||||
';
|
||||
public function getDeliveryDetails();
|
||||
public function getSocketsForSetupWizardToProbe($hostname, $smtpServerGuess);
|
||||
public function getConfigurationBid(PostmanWizardSocket $hostData, $userAuthOverride, $originalSmtpServer);
|
||||
public function isLockingRequired();
|
||||
public function createMailEngine();
|
||||
public function isWizardSupported();
|
||||
public function isConfiguredAndReady();
|
||||
public function isReadyToSendMail();
|
||||
public function getFromEmailAddress();
|
||||
public function getFromName();
|
||||
public function getHostname();
|
||||
public function getProtocol();
|
||||
public function isEmailValidationSupported();
|
||||
public function getPort();
|
||||
public function init();
|
||||
}
|
||||
interface PostmanZendModuleTransport extends PostmanModuleTransport {
|
||||
public function getAuthenticationType();
|
||||
public function getSecurityType();
|
||||
public function getCredentialsId();
|
||||
public function getCredentialsSecret();
|
||||
public function getEnvelopeFromEmailAddress();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jasonhendriks
|
||||
*
|
||||
*/
|
||||
abstract class PostmanAbstractModuleTransport implements PostmanModuleTransport {
|
||||
private $configurationMessages;
|
||||
private $configuredAndReady;
|
||||
|
||||
/**
|
||||
* These internal variables are exposed for the subclasses to use
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
protected $logger;
|
||||
protected $options;
|
||||
protected $rootPluginFilenameAndPath;
|
||||
protected $scribe;
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __construct($rootPluginFilenameAndPath = null) {
|
||||
$this->logger = new PostmanLogger ( get_class ( $this ) );
|
||||
$this->options = PostmanOptions::getInstance ();
|
||||
$this->rootPluginFilenameAndPath = $rootPluginFilenameAndPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the Module
|
||||
*
|
||||
* Perform validation and create configuration error messages.
|
||||
* The module is not in a configured-and-ready state until initialization
|
||||
*/
|
||||
public function init() {
|
||||
// create the scribe
|
||||
$hostname = $this->getHostname ();
|
||||
$this->scribe = $this->createScribe ( $hostname );
|
||||
|
||||
// validate the transport and generate error messages
|
||||
$this->configurationMessages = $this->validateTransportConfiguration ();
|
||||
}
|
||||
|
||||
/**
|
||||
* SendGrid API doesn't care what the hostname or guessed SMTP Server is; it runs it's port test no matter what
|
||||
*/
|
||||
public function getSocketsForSetupWizardToProbe($hostname, $smtpServerGuess) {
|
||||
$hosts = array (
|
||||
self::createSocketDefinition ( $this->getHostname (), $this->getPort () )
|
||||
);
|
||||
return $hosts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a single socket for the Wizard to test
|
||||
*
|
||||
* @since 2.1 added `logo_url`
|
||||
*/
|
||||
protected function createSocketDefinition($hostname, $port) {
|
||||
|
||||
$socket = array ();
|
||||
$socket ['host'] = $hostname;
|
||||
$socket ['port'] = $port;
|
||||
$socket ['id'] = sprintf ( '%s-%s', $this->getSlug (), $port );
|
||||
$socket ['transport_id'] = $this->getSlug ();
|
||||
$socket ['transport_name'] = $this->getName ();
|
||||
$socket ['smtp'] = false;
|
||||
$socket['logo_url'] = $this->getLogoURL();
|
||||
|
||||
return $socket;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mixed $data
|
||||
*/
|
||||
public function prepareOptionsForExport($data) {
|
||||
// no-op
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Status of OAuth
|
||||
*
|
||||
* @since 2.1 Removed HTML
|
||||
*/
|
||||
public function printActionMenuItem() {
|
||||
echo $this->getScribe ()->getRequestPermissionLinkText ();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mixed $queryHostname
|
||||
*/
|
||||
protected function createScribe($hostname) {
|
||||
$scribe = new PostmanNonOAuthScribe ( $hostname );
|
||||
return $scribe;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function enqueueScript() {
|
||||
// no-op, this for subclasses
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is for internal use
|
||||
*/
|
||||
protected function validateTransportConfiguration() {
|
||||
$this->configuredAndReady = true;
|
||||
$messages = array ();
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
protected function setNotConfiguredAndReady() {
|
||||
$this->configuredAndReady = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* A short-hand way of showing the complete delivery method
|
||||
*
|
||||
* @param PostmanModuleTransport $transport
|
||||
* @return string
|
||||
*/
|
||||
public function getPublicTransportUri() {
|
||||
$name = $this->getSlug ();
|
||||
$host = $this->getHostname ();
|
||||
$port = $this->getPort ();
|
||||
$protocol = $this->getProtocol ();
|
||||
return sprintf ( '%s://%s:%s', $protocol, $host, $port );
|
||||
}
|
||||
|
||||
/**
|
||||
* The Message From Address
|
||||
*/
|
||||
public function getFromEmailAddress() {
|
||||
return PostmanOptions::getInstance ()->getMessageSenderEmail ();
|
||||
}
|
||||
|
||||
/**
|
||||
* The Message From Name
|
||||
*/
|
||||
public function getFromName() {
|
||||
return PostmanOptions::getInstance ()->getMessageSenderName ();
|
||||
}
|
||||
public function getEnvelopeFromEmailAddress() {
|
||||
return PostmanOptions::getInstance ()->getEnvelopeSender ();
|
||||
}
|
||||
public function isEmailValidationSupported() {
|
||||
return ! PostmanOptions::getInstance ()->isEmailValidationDisabled ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure the Senders are configured
|
||||
*
|
||||
* @param PostmanOptions $options
|
||||
* @return boolean
|
||||
*/
|
||||
protected function isSenderConfigured() {
|
||||
$options = PostmanOptions::getInstance ();
|
||||
$messageFrom = $options->getMessageSenderEmail ();
|
||||
return ! empty ( $messageFrom );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the configuration error messages
|
||||
*/
|
||||
public function getConfigurationMessages() {
|
||||
return $this->configurationMessages;
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanModuleTransport::isConfiguredAndReady()
|
||||
*/
|
||||
public function isConfiguredAndReady() {
|
||||
return $this->configuredAndReady;
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanModuleTransport::isReadyToSendMail()
|
||||
*/
|
||||
public function isReadyToSendMail() {
|
||||
return $this->isConfiguredAndReady ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether Mail Engine locking is needed
|
||||
*
|
||||
* @see PostmanModuleTransport::requiresLocking()
|
||||
*/
|
||||
public function isLockingRequired() {
|
||||
return false;
|
||||
}
|
||||
public function isOAuthUsed($authType) {
|
||||
return $authType == PostmanOptions::AUTHENTICATION_TYPE_OAUTH2;
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanModuleTransport::isWizardSupported()
|
||||
*/
|
||||
public function isWizardSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is for step 2 of the Wizard
|
||||
*/
|
||||
public function printWizardMailServerHostnameStep() {
|
||||
}
|
||||
|
||||
/**
|
||||
* This is for step 4 of the Wizard
|
||||
*/
|
||||
public function printWizardAuthenticationStep() {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return PostmanNonOAuthScribe
|
||||
*/
|
||||
public function getScribe() {
|
||||
return $this->scribe;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mixed $hostname
|
||||
* @param mixed $response
|
||||
*/
|
||||
public function populateConfiguration($hostname) {
|
||||
$configuration = array ();
|
||||
return $configuration;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param mixed $winningRecommendation
|
||||
* @param mixed $response
|
||||
*/
|
||||
public function populateConfigurationFromRecommendation($winningRecommendation) {
|
||||
$configuration = array ();
|
||||
$configuration ['message'] = $winningRecommendation ['message'];
|
||||
$configuration [PostmanOptions::TRANSPORT_TYPE] = $winningRecommendation ['transport'];
|
||||
return $configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function createOverrideMenu(PostmanWizardSocket $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride) {
|
||||
|
||||
$overrideItem = array ();
|
||||
$overrideItem ['secure'] = $socket->secure;
|
||||
$overrideItem ['mitm'] = $socket->mitm;
|
||||
$overrideItem ['hostname_domain_only'] = $socket->hostnameDomainOnly;
|
||||
$overrideItem ['reported_hostname_domain_only'] = $socket->reportedHostnameDomainOnly;
|
||||
$overrideItem ['value'] = $socket->id;
|
||||
$overrideItem ['description'] = $socket->label;
|
||||
$overrideItem ['selected'] = ($winningRecommendation ['id'] == $overrideItem ['value']);
|
||||
$overrideItem['data'] = $socket->data;
|
||||
|
||||
return $overrideItem;
|
||||
}
|
||||
|
||||
/*
|
||||
* ******************************************************************
|
||||
* Not deprecated, but I wish they didn't live here on the superclass
|
||||
*/
|
||||
public function isServiceProviderGoogle($hostname) {
|
||||
return PostmanUtils::endsWith ( $hostname, 'gmail.com' ) || PostmanUtils::endsWith ( $hostname, 'googleapis.com' );
|
||||
}
|
||||
public function isServiceProviderMicrosoft($hostname) {
|
||||
return PostmanUtils::endsWith ( $hostname, 'live.com' );
|
||||
}
|
||||
public function isServiceProviderYahoo($hostname) {
|
||||
|
||||
if( $hostname == null ) {
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
return strpos ( $hostname, 'yahoo' );
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* ********************************
|
||||
* Unused, deprecated methods follow
|
||||
* *********************************
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @deprecated (non-PHPdoc)
|
||||
* @see PostmanTransport::createZendMailTransport()
|
||||
*/
|
||||
public function createZendMailTransport($hostname, $config) {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @deprecated (non-PHPdoc)
|
||||
* @see PostmanTransport::isTranscriptSupported()
|
||||
*/
|
||||
public function isTranscriptSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Only here because I can't remove it from the Interface
|
||||
*/
|
||||
public final function getMisconfigurationMessage(PostmanConfigTextHelper $scribe, PostmanOptionsInterface $options, PostmanOAuthToken $token) {
|
||||
}
|
||||
public final function isReady(PostmanOptionsInterface $options, PostmanOAuthToken $token) {
|
||||
return ! ($this->isConfiguredAndReady ());
|
||||
}
|
||||
public final function isConfigured(PostmanOptionsInterface $options, PostmanOAuthToken $token) {
|
||||
return ! ($this->isConfiguredAndReady ());
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @deprecated (non-PHPdoc)
|
||||
* @see PostmanTransport::getConfigurationRecommendation()
|
||||
*/
|
||||
public final function getConfigurationRecommendation($hostData) {
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @deprecated (non-PHPdoc)
|
||||
* @see PostmanTransport::getHostsToTest()
|
||||
*/
|
||||
public final function getHostsToTest($hostname) {
|
||||
}
|
||||
protected final function isHostConfigured(PostmanOptions $options) {
|
||||
$hostname = $options->getHostname ();
|
||||
$port = $options->getPort ();
|
||||
return ! (empty ( $hostname ) || empty ( $port ));
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @deprecated (non-PHPdoc)
|
||||
* @see PostmanTransport::createPostmanMailAuthenticator()
|
||||
*/
|
||||
public final function createPostmanMailAuthenticator(PostmanOptions $options, PostmanOAuthToken $authToken) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For the transports which depend on Zend_Mail
|
||||
*
|
||||
* @author jasonhendriks
|
||||
*
|
||||
*/
|
||||
abstract class PostmanAbstractZendModuleTransport extends PostmanAbstractModuleTransport implements PostmanZendModuleTransport {
|
||||
private $oauthToken;
|
||||
private $readyForOAuthGrant;
|
||||
|
||||
/**
|
||||
*/
|
||||
public function __construct($rootPluginFilenameAndPath) {
|
||||
parent::__construct ( $rootPluginFilenameAndPath );
|
||||
$this->oauthToken = PostmanOAuthToken::getInstance ();
|
||||
}
|
||||
public function getOAuthToken() {
|
||||
return $this->oauthToken;
|
||||
}
|
||||
public function getProtocol() {
|
||||
if ($this->getSecurityType () == PostmanOptions::SECURITY_TYPE_SMTPS)
|
||||
return 'smtps';
|
||||
else
|
||||
return 'smtp';
|
||||
}
|
||||
public function getSecurityType() {
|
||||
return PostmanOptions::getInstance ()->getEncryptionType ();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mixed $data
|
||||
*/
|
||||
public function prepareOptionsForExport($data) {
|
||||
$data = parent::prepareOptionsForExport ( $data );
|
||||
$data [PostmanOptions::BASIC_AUTH_PASSWORD] = PostmanOptions::getInstance ()->getPassword ();
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isEnvelopeFromValidationSupported() {
|
||||
return $this->isEmailValidationSupported ();
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
protected function setReadyForOAuthGrant() {
|
||||
$this->readyForOAuthGrant = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Link of OAuth
|
||||
*
|
||||
* @since 2.1 Removed `li` tag
|
||||
*/
|
||||
public function printActionMenuItem() {
|
||||
if ($this->readyForOAuthGrant && $this->getAuthenticationType () == PostmanOptions::AUTHENTICATION_TYPE_OAUTH2) {
|
||||
echo '<a href="'.esc_attr( PostmanUtils::getGrantOAuthPermissionUrl () ).'" class="welcome-icon send-test-email">'.esc_html( $this->getScribe ()->getRequestPermissionLinkText () ).'</a>';
|
||||
} else {
|
||||
parent::printActionMenuItem ();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mixed $queryHostname
|
||||
*/
|
||||
protected function createScribe($hostname) {
|
||||
$scribe = null;
|
||||
if ($this->isServiceProviderGoogle ( $hostname )) {
|
||||
$scribe = new PostmanGoogleOAuthScribe ();
|
||||
} else if ($this->isServiceProviderMicrosoft ( $hostname )) {
|
||||
$scribe = new PostmanMicrosoftOAuthScribe ();
|
||||
} else if ($this->isServiceProviderYahoo ( $hostname )) {
|
||||
$scribe = new PostmanYahooOAuthScribe ();
|
||||
} else {
|
||||
$scribe = new PostmanNonOAuthScribe ( $hostname );
|
||||
}
|
||||
return $scribe;
|
||||
}
|
||||
|
||||
/**
|
||||
* A short-hand way of showing the complete delivery method
|
||||
*
|
||||
* @param PostmanModuleTransport $transport
|
||||
* @return string
|
||||
*/
|
||||
public function getPublicTransportUri() {
|
||||
$transportName = $this->getSlug ();
|
||||
$options = PostmanOptions::getInstance ();
|
||||
$auth = $this->getAuthenticationType ( $options );
|
||||
$protocol = $this->getProtocol ();
|
||||
$security = $this->getSecurityType ();
|
||||
$host = $this->getHostname ( $options );
|
||||
$port = $this->getPort ( $options );
|
||||
if (! empty ( $security ) && $security != 'ssl') {
|
||||
return sprintf ( '%s:%s:%s://%s:%s', $protocol, $security, $auth, $host, $port );
|
||||
} else {
|
||||
return sprintf ( '%s:%s://%s:%s', $protocol, $auth, $host, $port );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanModuleTransport::getDeliveryDetails()
|
||||
*/
|
||||
public function getDeliveryDetails() {
|
||||
$this->options = $this->options;
|
||||
$deliveryDetails ['transport_name'] = $this->getTransportDescription ( $this->getSecurityType () );
|
||||
$deliveryDetails ['host'] = $this->getHostname () . ':' . $this->getPort ();
|
||||
$deliveryDetails ['auth_desc'] = $this->getAuthenticationDescription ( $this->getAuthenticationType () );
|
||||
|
||||
if ( $deliveryDetails ['host'] == 'localhost:25' ) {
|
||||
$deliveryDetails ['transport_name'] = __( 'Sendmail (server default - not SMTP)', 'post-smtp');
|
||||
}
|
||||
|
||||
/* translators: where (1) is the transport type, (2) is the host, and (3) is the Authentication Type (e.g. Postman will send mail via smtp.gmail.com:465 using OAuth 2.0 authentication.) */
|
||||
return sprintf ( __ ( 'Postman will send mail via %1$s to %2$s using %3$s authentication.', 'post-smtp' ), '<b>' . $deliveryDetails ['transport_name'] . '</b>', '<b>' . $deliveryDetails ['host'] . '</b>', '<b>' . $deliveryDetails ['auth_desc'] . '</b>' );
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mixed $encType
|
||||
* @return string
|
||||
*/
|
||||
protected function getTransportDescription($encType) {
|
||||
$deliveryDetails = '🔓SMTP';
|
||||
if ($encType == PostmanOptions::SECURITY_TYPE_SMTPS) {
|
||||
/* translators: where %1$s is the Transport type (e.g. SMTP or SMTPS) and %2$s is the encryption type (e.g. SSL or TLS) */
|
||||
$deliveryDetails = '🔐SMTPS';
|
||||
} else if ($encType == PostmanOptions::SECURITY_TYPE_STARTTLS) {
|
||||
/* translators: where %1$s is the Transport type (e.g. SMTP or SMTPS) and %2$s is the encryption type (e.g. SSL or TLS) */
|
||||
$deliveryDetails = '🔐SMTP-STARTTLS';
|
||||
}
|
||||
return $deliveryDetails;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mixed $authType
|
||||
*/
|
||||
protected function getAuthenticationDescription($authType) {
|
||||
if (PostmanOptions::AUTHENTICATION_TYPE_OAUTH2 == $authType) {
|
||||
return 'OAuth 2.0';
|
||||
} else if (PostmanOptions::AUTHENTICATION_TYPE_NONE == $authType) {
|
||||
return _x ( 'no', 'as in "There is no Spoon"', 'post-smtp' );
|
||||
} else {
|
||||
switch ($authType) {
|
||||
case PostmanOptions::AUTHENTICATION_TYPE_CRAMMD5 :
|
||||
$authDescription = 'CRAM-MD5';
|
||||
break;
|
||||
|
||||
case PostmanOptions::AUTHENTICATION_TYPE_LOGIN :
|
||||
$authDescription = 'Login';
|
||||
break;
|
||||
|
||||
case PostmanOptions::AUTHENTICATION_TYPE_PLAIN :
|
||||
$authDescription = 'Plain';
|
||||
break;
|
||||
|
||||
default :
|
||||
$authDescription = $authType;
|
||||
break;
|
||||
}
|
||||
return sprintf ( '%s (%s)', __ ( 'Password', 'post-smtp' ), $authDescription );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure the Senders are configured
|
||||
*
|
||||
* @param PostmanOptions $options
|
||||
* @return boolean
|
||||
*/
|
||||
protected function isEnvelopeFromConfigured() {
|
||||
$options = PostmanOptions::getInstance ();
|
||||
$envelopeFrom = $options->getEnvelopeSender ();
|
||||
return ! empty ( $envelopeFrom );
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanTransport::getMisconfigurationMessage()
|
||||
*/
|
||||
protected function validateTransportConfiguration() {
|
||||
parent::validateTransportConfiguration ();
|
||||
$messages = parent::validateTransportConfiguration ();
|
||||
if (! $this->isSenderConfigured ()) {
|
||||
array_push ( $messages, __ ( 'Message From Address can not be empty', 'post-smtp' ) . '.' );
|
||||
$this->setNotConfiguredAndReady ();
|
||||
}
|
||||
if ($this->getAuthenticationType () == PostmanOptions::AUTHENTICATION_TYPE_OAUTH2) {
|
||||
if (! $this->isOAuth2ClientIdAndClientSecretConfigured ()) {
|
||||
/* translators: %1$s is the Client ID label, and %2$s is the Client Secret label (e.g. Warning: OAuth 2.0 authentication requires an OAuth 2.0-capable Outgoing Mail Server, Sender Email Address, Client ID, and Client Secret.) */
|
||||
array_push ( $messages, sprintf ( __ ( 'OAuth 2.0 authentication requires a %1$s and %2$s.', 'post-smtp' ), $this->getScribe ()->getClientIdLabel (), $this->getScribe ()->getClientSecretLabel () ) );
|
||||
$this->setNotConfiguredAndReady ();
|
||||
}
|
||||
}
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
protected function isOAuth2ClientIdAndClientSecretConfigured() {
|
||||
$options = PostmanOptions::getInstance ();
|
||||
$clientId = $options->getClientId ();
|
||||
$clientSecret = $options->getClientSecret ();
|
||||
return ! (empty ( $clientId ) || empty ( $clientSecret ));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
protected function isPasswordAuthenticationConfigured(PostmanOptions $options) {
|
||||
$username = $options->getUsername ();
|
||||
$password = $options->getPassword ();
|
||||
return $this->options->isAuthTypePassword () && ! (empty ( $username ) || empty ( $password ));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
protected function isPermissionNeeded() {
|
||||
$accessToken = $this->getOAuthToken ()->getAccessToken ();
|
||||
$refreshToken = $this->getOAuthToken ()->getRefreshToken ();
|
||||
return $this->isOAuthUsed ( PostmanOptions::getInstance ()->getAuthenticationType () ) && (empty ( $accessToken ) || empty ( $refreshToken ));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mixed $hostname
|
||||
* @param mixed $response
|
||||
*/
|
||||
public function populateConfiguration($hostname) {
|
||||
$response = parent::populateConfiguration ( $hostname );
|
||||
$this->logger->debug ( sprintf ( 'populateConfigurationFromRecommendation for hostname %s', $hostname ) );
|
||||
$scribe = $this->createScribe ( $hostname );
|
||||
// checks to see if the host is an IP address and sticks the result in the response
|
||||
// IP addresses are not allowed in the Redirect URL
|
||||
$urlParts = parse_url ( $scribe->getCallbackUrl () );
|
||||
$response ['dot_notation_url'] = false;
|
||||
if (isset ( $urlParts ['host'] )) {
|
||||
if (PostmanUtils::isHostAddressNotADomainName ( $urlParts ['host'] )) {
|
||||
$response ['dot_notation_url'] = true;
|
||||
}
|
||||
}
|
||||
$response ['redirect_url'] = $scribe->getCallbackUrl ();
|
||||
$response ['callback_domain'] = $scribe->getCallbackDomain ();
|
||||
$response ['help_text'] = $scribe->getOAuthHelp ();
|
||||
$response ['client_id_label'] = $scribe->getClientIdLabel ();
|
||||
$response ['client_secret_label'] = $scribe->getClientSecretLabel ();
|
||||
$response ['redirect_url_label'] = $scribe->getCallbackUrlLabel ();
|
||||
$response ['callback_domain_label'] = $scribe->getCallbackDomainLabel ();
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the Ajax response for the Setup Wizard / Manual Configuration
|
||||
*
|
||||
* @param mixed $hostname
|
||||
* @param mixed $response
|
||||
*/
|
||||
public function populateConfigurationFromRecommendation($winningRecommendation) {
|
||||
$response = parent::populateConfigurationFromRecommendation ( $winningRecommendation );
|
||||
$response [PostmanOptions::AUTHENTICATION_TYPE] = $winningRecommendation ['auth'];
|
||||
if (isset ( $winningRecommendation ['enc'] )) {
|
||||
$response [PostmanOptions::SECURITY_TYPE] = $winningRecommendation ['enc'];
|
||||
}
|
||||
if (isset ( $winningRecommendation ['port'] )) {
|
||||
$response [PostmanOptions::PORT] = $winningRecommendation ['port'];
|
||||
}
|
||||
if (isset ( $winningRecommendation ['hostname'] )) {
|
||||
$response [PostmanOptions::HOSTNAME] = $winningRecommendation ['hostname'];
|
||||
}
|
||||
if (isset ( $winningRecommendation ['display_auth'] )) {
|
||||
$response ['display_auth'] = $winningRecommendation ['display_auth'];
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @version 1.0
|
||||
*/
|
||||
public function createOverrideMenu(PostmanWizardSocket $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride) {
|
||||
$overrideItem = parent::createOverrideMenu ( $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride );
|
||||
$selected = $overrideItem ['selected'];
|
||||
$password_field = __( 'Password', 'post-smtp' );
|
||||
|
||||
if( $winningRecommendation['hostname'] == 'smtp.gmail.com' ) {
|
||||
$password_field = sprintf(
|
||||
'%s <a href="%s" target="_blank">%s</a>',
|
||||
__( 'App Password', 'post-smtp' ),
|
||||
esc_url( 'https://postmansmtp.com/documentation/#setting-up-an-app-password-in-your-google-account' ),
|
||||
__( 'How to Setup an App Password', 'post-smtp' )
|
||||
);
|
||||
}
|
||||
|
||||
// only smtp can have multiple auth options
|
||||
$overrideAuthItems = array ();
|
||||
$passwordMode = false;
|
||||
$oauth2Mode = false;
|
||||
$noAuthMode = false;
|
||||
if (isset ( $userAuthOverride ) || isset ( $userSocketOverride )) {
|
||||
if ($userAuthOverride == 'password') {
|
||||
$passwordMode = true;
|
||||
} elseif ($userAuthOverride == 'oauth2') {
|
||||
$oauth2Mode = true;
|
||||
} else {
|
||||
$noAuthMode = true;
|
||||
}
|
||||
} else {
|
||||
if ( isset( $winningRecommendation ['display_auth'] ) && $winningRecommendation ['display_auth'] == 'password') {
|
||||
$passwordMode = true;
|
||||
} elseif ( isset( $winningRecommendation ['display_auth'] ) && $winningRecommendation ['display_auth'] == 'oauth2') {
|
||||
$oauth2Mode = true;
|
||||
} else {
|
||||
$noAuthMode = true;
|
||||
}
|
||||
}
|
||||
if ($selected) {
|
||||
if ($socket->auth_crammd5 || $socket->auth_login || $socket->authPlain) {
|
||||
array_push ( $overrideAuthItems, array (
|
||||
'selected' => $passwordMode,
|
||||
'name' => $password_field,
|
||||
'value' => 'password'
|
||||
) );
|
||||
}
|
||||
if ($socket->auth_xoauth || $winningRecommendation ['auth'] == 'oauth2') {
|
||||
array_push ( $overrideAuthItems, array (
|
||||
'selected' => $oauth2Mode,
|
||||
'name' => __ ( 'OAuth 2.0 (requires Client ID and Client Secret)', 'post-smtp' ),
|
||||
'value' => 'oauth2'
|
||||
) );
|
||||
}
|
||||
if ($socket->auth_none) {
|
||||
array_push ( $overrideAuthItems, array (
|
||||
'selected' => $noAuthMode,
|
||||
'name' => __ ( 'None', 'post-smtp' ),
|
||||
'value' => 'none'
|
||||
) );
|
||||
}
|
||||
|
||||
// marks at least one item as selected if none are selected
|
||||
$atLeastOneSelected = false;
|
||||
$firstItem = null;
|
||||
// don't use variable reference see http://stackoverflow.com/questions/15024616/php-foreach-change-original-array-values
|
||||
foreach ( $overrideAuthItems as $key => $field ) {
|
||||
if (! $firstItem) {
|
||||
$firstItem = $key;
|
||||
}
|
||||
if ($field ['selected']) {
|
||||
$atLeastOneSelected = true;
|
||||
}
|
||||
}
|
||||
if (! $atLeastOneSelected) {
|
||||
$this->logger->debug ( 'nothing selected - forcing a selection on the *first* overrided auth item' );
|
||||
$overrideAuthItems [$firstItem] ['selected'] = true;
|
||||
}
|
||||
|
||||
// push the authentication options into the $overrideItem structure
|
||||
$overrideItem ['auth_items'] = $overrideAuthItems;
|
||||
}
|
||||
return $overrideItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Socket's logo
|
||||
*
|
||||
* @since 2.1
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getLogoURL() {
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,223 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
define( 'MAILSTER_POSTMAN_REQUIRED_VERSION', '2.0' );
|
||||
define( 'MAILSTER_POSTMAN_ID', 'postman' );
|
||||
|
||||
/**
|
||||
* Enables Mailster to deliver via Postman
|
||||
*
|
||||
* @author jasonhendriks
|
||||
*/
|
||||
if ( ! class_exists( 'PostmanMyMailConnector' ) ) {
|
||||
class PostmanMyMailConnector {
|
||||
|
||||
// PostmanLogger
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* No-argument constructor
|
||||
*/
|
||||
public function __construct( $file ) {
|
||||
register_activation_hook( $file, array(
|
||||
$this,
|
||||
'activate',
|
||||
) );
|
||||
register_deactivation_hook( $file, array(
|
||||
$this,
|
||||
'deactivate',
|
||||
) );
|
||||
|
||||
add_action( 'init', array(
|
||||
$this,
|
||||
'init',
|
||||
), 1 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the Connector
|
||||
*/
|
||||
public function init() {
|
||||
if ( ! defined( 'MAILSTER_VERSION' ) || version_compare( MAILSTER_POSTMAN_REQUIRED_VERSION, MAILSTER_VERSION, '>' ) ) {
|
||||
// no-op
|
||||
} else {
|
||||
// create an instance of the Logger
|
||||
$this->logger = new PostmanLogger( get_class( $this ) );
|
||||
$this->logger->debug( 'Starting' );
|
||||
|
||||
add_filter( 'mailster_delivery_methods', array(
|
||||
&$this,
|
||||
'delivery_method',
|
||||
) );
|
||||
add_action( 'mailster_deliverymethod_tab_postman', array(
|
||||
&$this,
|
||||
'deliverytab',
|
||||
) );
|
||||
|
||||
if ( mailster_option( 'deliverymethod' ) == MAILSTER_POSTMAN_ID ) {
|
||||
add_action( 'mailster_initsend', array(
|
||||
&$this,
|
||||
'initsend',
|
||||
) );
|
||||
add_action( 'mailster_presend', array(
|
||||
&$this,
|
||||
'presend',
|
||||
) );
|
||||
add_action( 'mailster_dosend', array(
|
||||
&$this,
|
||||
'dosend',
|
||||
) );
|
||||
add_action( 'MAILSTER_POSTMAN_cron', array(
|
||||
&$this,
|
||||
'reset',
|
||||
) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* initsend function.
|
||||
*
|
||||
* uses mailster_initsend hook to set initial settings
|
||||
*
|
||||
* @access public
|
||||
* @param mixed $mailobject
|
||||
* @return void
|
||||
*/
|
||||
public function initsend( $mailobject ) {
|
||||
$this->logger->trace( 'initsend' );
|
||||
// disable dkim
|
||||
$mailobject->dkim = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* presend function.
|
||||
*
|
||||
* uses the mailster_presend hook to apply setttings before each mail
|
||||
*
|
||||
* @access public
|
||||
* @param mixed $mailobject
|
||||
* @return void
|
||||
*/
|
||||
public function presend( $mailobject ) {
|
||||
|
||||
// embedding images doesn't work
|
||||
$mailobject->embed_images = false;
|
||||
|
||||
// use pre_send from the main class
|
||||
// need the raw email body to send so we use the same option
|
||||
$mailobject->pre_send();
|
||||
}
|
||||
|
||||
/**
|
||||
* dosend function.
|
||||
*
|
||||
* uses the mailster_dosend hook and triggers the send
|
||||
*
|
||||
* @access public
|
||||
* @param mixed $mailobject
|
||||
* @return void
|
||||
*/
|
||||
public function dosend( $mailobject ) {
|
||||
$this->logger->trace( 'dosend' );
|
||||
$this->logger->trace( $mailobject->mailer );
|
||||
|
||||
// create a PostmanWpMail instance
|
||||
$postmanWpMail = new PostmanWpMail();
|
||||
$postmanWpMail->init();
|
||||
|
||||
// create a PostmanMessage instance
|
||||
$message = $postmanWpMail->createNewMessage();
|
||||
$message->addHeaders( $mailobject->headers );
|
||||
$message->setBodyTextPart( $mailobject->mailer->AltBody );
|
||||
$message->setBodyHtmlPart( $mailobject->mailer->Body );
|
||||
$message->setBody( $mailobject->mailer->AltBody . $mailobject->mailer->Body );
|
||||
$message->setSubject( $mailobject->subject );
|
||||
$message->addTo( $mailobject->to );
|
||||
$message->setReplyTo( $mailobject->reply_to );
|
||||
$message->setAttachments( $mailobject->attachments );
|
||||
|
||||
// create a PostmanEmailLog instance
|
||||
$log = new PostmanEmailLog();
|
||||
|
||||
// send the message and store the result
|
||||
$mailobject->sent = $postmanWpMail->sendMessage( $message, $log );
|
||||
|
||||
// give error message back to MyMail
|
||||
$result = apply_filters( 'postman_wp_mail_result', null );
|
||||
if ( ! $mailobject->sent ) {
|
||||
$mailobject->set_error( $result ['exception']->getMessage() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* reset function.
|
||||
*
|
||||
* resets the current time
|
||||
*
|
||||
* @access public
|
||||
* @param mixed $message
|
||||
*/
|
||||
public function reset() {
|
||||
update_option( '_transient__mailster_send_period_timeout', false );
|
||||
update_option( '_transient__mailster_send_period', 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* delivery_method function.
|
||||
*
|
||||
* add the delivery method to the options
|
||||
*
|
||||
* @access public
|
||||
* @param mixed $delivery_methods
|
||||
* @return mixed
|
||||
*/
|
||||
public function delivery_method( $delivery_methods ) {
|
||||
$delivery_methods [ MAILSTER_POSTMAN_ID ] = __( 'Postman SMTP', 'post-smtp' );
|
||||
return $delivery_methods;
|
||||
}
|
||||
|
||||
/**
|
||||
* deliverytab function.
|
||||
*
|
||||
* the content of the tab for the options
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function deliverytab() {
|
||||
apply_filters( 'print_postman_status', null );
|
||||
}
|
||||
|
||||
/**
|
||||
* activate function.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function activate() {
|
||||
if ( defined( 'MAILSTER_VERSION' ) && version_compare( MAILSTER_POSTMAN_REQUIRED_VERSION, MAILSTER_VERSION, '<=' ) ) {
|
||||
mailster_notice( sprintf( __( 'Mailster: Change the delivery method in the %s!', 'post-smtp' ), sprintf( '<a href="edit.php?post_type=newsletter&page=mailster_settings&mailster_remove_notice=mailster_delivery_method#delivery">%s</a>', __( 'Settings', 'postman-smtp' ) ) ), '', false, 'delivery_method' );
|
||||
$this->reset();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* deactivate function.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function deactivate() {
|
||||
if ( defined( 'MAILSTER_VERSION' ) && function_exists( 'mailster_option' ) && version_compare( MAILSTER_POSTMAN_REQUIRED_VERSION, MAILSTER_VERSION, '<=' ) ) {
|
||||
if ( mailster_option( 'deliverymethod' ) == MAILSTER_POSTMAN_ID ) {
|
||||
mailster_update_option( 'deliverymethod', 'simple' );
|
||||
/* Translators where %s is the name of the page */
|
||||
mailster_notice( sprintf( __( 'Mailster: Change the delivery method in the %s!', 'post-smtp' ), sprintf( '<a href="edit.php?post_type=newsletter&page=mailster_settings&mailster_remove_notice=mailster_delivery_method#delivery">%s</a>', __( 'Settings', 'postman-smtp' ) ) ), '', false, 'delivery_method' );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
if( !class_exists( 'PostmanPostmarkMailEngine' ) ):
|
||||
|
||||
require_once 'Services/PostMark/Handler.php';
|
||||
|
||||
class PostmanPostmarkMailEngine implements PostmanMailEngine {
|
||||
|
||||
protected $logger;
|
||||
|
||||
private $transcript;
|
||||
|
||||
private $api_key;
|
||||
|
||||
/**
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function __construct( $api_key ) {
|
||||
assert( !empty( $api_key ) );
|
||||
$this->api_key = $api_key;
|
||||
|
||||
// create the logger
|
||||
$this->logger = new PostmanLogger( get_class( $this ) );
|
||||
|
||||
}
|
||||
|
||||
public function getTranscript() {
|
||||
return $this->transcript;
|
||||
}
|
||||
|
||||
private function addAttachmentsToMail( PostmanMessage $message ) {
|
||||
|
||||
$attachments = $message->getAttachments();
|
||||
|
||||
if ( ! is_array( $attachments ) ) {
|
||||
// WordPress may a single filename or a newline-delimited string list of multiple filenames
|
||||
$attArray = explode( PHP_EOL, $attachments );
|
||||
} else {
|
||||
$attArray = $attachments;
|
||||
}
|
||||
// otherwise WordPress sends an array
|
||||
$attachments = array();
|
||||
foreach ( $attArray as $file ) {
|
||||
if ( ! empty( $file ) ) {
|
||||
$this->logger->debug( 'Adding attachment: ' . $file );
|
||||
|
||||
$file_name = basename( $file );
|
||||
$file_parts = explode( '.', $file_name );
|
||||
$file_type = wp_check_filetype( $file );
|
||||
$attachments[] = array(
|
||||
'content' => base64_encode( file_get_contents( $file ) ),
|
||||
'type' => $file_type['type'],
|
||||
'file_name' => $file_name,
|
||||
'disposition' => 'attachment',
|
||||
'id' => $file_parts[0],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $attachments;
|
||||
|
||||
}
|
||||
|
||||
public function send( PostmanMessage $message ) {
|
||||
|
||||
$options = PostmanOptions::getInstance();
|
||||
|
||||
if ( $this->logger->isDebug() ) {
|
||||
$this->logger->debug( 'Creating PostMark service with api_Key=' . $this->api_key );
|
||||
}
|
||||
|
||||
$post_mark = new PostmanPostMark( $this->api_key );
|
||||
$body = $this->get_email_body( $message );
|
||||
|
||||
try {
|
||||
$response = $post_mark->send( $body );
|
||||
// send the message
|
||||
if ( $this->logger->isDebug() ) {
|
||||
$this->logger->debug( 'Sending mail' );
|
||||
}
|
||||
|
||||
$this->transcript = print_r( $response, true );
|
||||
$this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
|
||||
$this->transcript .= print_r( $body, true );
|
||||
$this->logger->debug( 'Transcript=' . $this->transcript );
|
||||
|
||||
} catch(Exception $exception) {
|
||||
|
||||
$this->transcript = $exception->getMessage();
|
||||
$this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
|
||||
$this->transcript .= print_r( $body, true );
|
||||
$this->logger->debug( 'Transcript=' . $this->transcript );
|
||||
|
||||
throw $exception;
|
||||
}
|
||||
}
|
||||
|
||||
private function get_email_body( $message ) {
|
||||
|
||||
if( is_a( $message, 'PostmanMessage' ) ) {
|
||||
|
||||
$options = PostmanOptions::getInstance();
|
||||
|
||||
$sender = $message->getFromAddress();
|
||||
$senderEmail = !empty( $sender->getEmail() ) ? $sender->getEmail() : $options->getMessageSenderEmail();
|
||||
|
||||
$sender->log( $this->logger, 'From' );
|
||||
|
||||
$body = $tos = $headers = $duplicates = $cc = $bcc = $email_attachments = array();
|
||||
$body['From'] = $senderEmail;
|
||||
|
||||
// add the to recipients
|
||||
foreach ( (array)$message->getToRecipients() as $recipient ) {
|
||||
|
||||
if ( !array_key_exists( $recipient->getEmail(), $duplicates ) ) {
|
||||
|
||||
$tos[] = $recipient->getEmail();
|
||||
|
||||
$duplicates[] = $recipient->getEmail();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$body['To'] = implode( ",", $tos );
|
||||
$body['Subject'] = $message->getSubject();
|
||||
|
||||
$textPart = $message->getBodyTextPart();
|
||||
if ( ! empty( $textPart ) ) {
|
||||
$this->logger->debug( 'Adding body as text' );
|
||||
$body['TextBody'] = $textPart;
|
||||
}
|
||||
|
||||
$htmlPart = $message->getBodyHtmlPart();
|
||||
if ( ! empty( $htmlPart ) ) {
|
||||
$this->logger->debug( 'Adding body as html' );
|
||||
$body['HtmlBody'] = $htmlPart;
|
||||
}
|
||||
|
||||
// add the reply-to
|
||||
$replyTo = $message->getReplyTo();
|
||||
// $replyTo is null or a PostmanEmailAddress object
|
||||
if ( isset( $replyTo ) ) {
|
||||
$body['ReplyTo'] = $replyTo->getEmail();
|
||||
} else {
|
||||
$body['ReplyTo'] = "";
|
||||
}
|
||||
|
||||
// add the Postman signature - append it to whatever the user may have set
|
||||
if ( ! $options->isStealthModeEnabled() ) {
|
||||
$pluginData = apply_filters( 'postman_get_plugin_metadata', null );
|
||||
$headers['X-Mailer'] = sprintf( 'Postman SMTP %s for WordPress (%s)', $pluginData ['version'], 'https://wordpress.org/plugins/post-smtp/' );
|
||||
}
|
||||
|
||||
foreach ( ( array ) $message->getHeaders() as $header ) {
|
||||
$this->logger->debug( sprintf( 'Adding user header %s=%s', $header ['name'], $header ['content'] ) );
|
||||
$headers[$header['name']] = $header ['content'];
|
||||
}
|
||||
|
||||
$body['Headers'][] = $headers;
|
||||
// add the messageId
|
||||
$messageId = $message->getMessageId();
|
||||
if ( ! empty( $messageId ) ) {
|
||||
$headers['message-id'] = $messageId;
|
||||
}
|
||||
|
||||
// if the caller set a Content-Type header, use it
|
||||
$contentType = $message->getContentType();
|
||||
if ( ! empty( $contentType ) ) {
|
||||
$this->logger->debug( 'Some header keys are reserved. You may not include any of the following reserved headers: x-sg-id, x-sg-eid, received, dkim-signature, Content-Type, Content-Transfer-Encoding, To, From, Subject, Reply-To, CC, BCC.' );
|
||||
}
|
||||
|
||||
$duplicates = array();
|
||||
foreach ( ( array ) $message->getCcRecipients() as $recipient ) {
|
||||
|
||||
if ( ! in_array( $recipient->getEmail(), $duplicates ) ) {
|
||||
|
||||
$recipient->log($this->logger, 'Cc');
|
||||
|
||||
$cc[] = $recipient->getEmail();
|
||||
|
||||
$duplicates[] = $recipient->getEmail();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if( !empty( $cc ) ) {
|
||||
$body['Cc'] = implode( ",", $cc );
|
||||
} else {
|
||||
$body['Cc'] = "";
|
||||
}
|
||||
|
||||
|
||||
$duplicates = array();
|
||||
foreach ( ( array ) $message->getBccRecipients() as $recipient ) {
|
||||
|
||||
if ( ! in_array( $recipient->getEmail(), $duplicates ) ) {
|
||||
|
||||
$recipient->log($this->logger, 'Bcc');
|
||||
$bcc[] = $recipient->getEmail();
|
||||
|
||||
$duplicates[] = $recipient->getEmail();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if( !empty( $bcc ) ) {
|
||||
$body['Bcc'] = implode( ",", $bcc );
|
||||
} else {
|
||||
$body['Bcc'] = "";
|
||||
}
|
||||
|
||||
// add attachments
|
||||
$this->logger->debug( 'Adding attachments' );
|
||||
|
||||
$attachments = $this->addAttachmentsToMail( $message );
|
||||
|
||||
$body['Attachments'] = array();
|
||||
if( !empty( $attachments ) ) {
|
||||
|
||||
foreach ( $attachments as $index => $attachment ) {
|
||||
|
||||
$email_attachments[] = array(
|
||||
'name' => $attachment['file_name'],
|
||||
'content' => $attachment['content'],
|
||||
'ContentType' => $attachment['type']
|
||||
);
|
||||
}
|
||||
|
||||
$body['Attachments'] = $email_attachments;
|
||||
|
||||
}
|
||||
|
||||
$body['MessageStream'] = 'outbound';
|
||||
|
||||
// Handle apostrophes in email address From names by escaping them for the Postmark API.
|
||||
$from_regex = "/(\"From\": \"[a-zA-Z\\d]+)*[\\\\]{2,}'/";
|
||||
|
||||
return $body;
|
||||
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
endif;
|
||||
@@ -0,0 +1,316 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once 'PostmanModuleTransport.php';
|
||||
|
||||
/**
|
||||
* Postman Postmark
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
if( !class_exists( 'PostmanPostmarkTransport' ) ):
|
||||
class PostmanPostmarkTransport extends PostmanAbstractModuleTransport implements PostmanModuleTransport {
|
||||
|
||||
const SLUG = 'postmark_api';
|
||||
const PORT = 587;
|
||||
const HOST = 'smtp.postmarkapp.com';
|
||||
const PRIORITY = 44000;
|
||||
const POSTMARK_AUTH_OPTIONS = 'postman_postmark_auth_options';
|
||||
const POSTMARK_AUTH_SECTION = 'postman_postmark_auth_section';
|
||||
|
||||
/**
|
||||
* PostmanPostmarkTransport constructor.
|
||||
* @param $rootPluginFilenameAndPath
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function __construct( $rootPluginFilenameAndPath ) {
|
||||
|
||||
parent::__construct ( $rootPluginFilenameAndPath );
|
||||
|
||||
// add a hook on the plugins_loaded event
|
||||
add_action ( 'admin_init', array ( $this, 'on_admin_init' ) );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getPort() {
|
||||
return self::PORT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getSlug() {
|
||||
return self::SLUG;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getProtocol() {
|
||||
return 'https';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getHostname() {
|
||||
return self::HOST;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getConfigurationBid( PostmanWizardSocket $hostData, $userAuthOverride, $originalSmtpServer ) {
|
||||
|
||||
$recommendation = array();
|
||||
$recommendation ['priority'] = 0;
|
||||
$recommendation ['transport'] = self::SLUG;
|
||||
$recommendation ['hostname'] = null; // scribe looks this
|
||||
$recommendation ['label'] = $this->getName();
|
||||
$recommendation['logo_url'] = $this->getLogoURL();
|
||||
|
||||
if ($hostData->hostname == self::HOST && $hostData->port == self::PORT) {
|
||||
$recommendation ['priority'] = self::PRIORITY;
|
||||
/* translators: where variables are (1) transport name (2) host and (3) port */
|
||||
$recommendation ['message'] = sprintf ( __ ( ('Postman recommends the %1$s to host %2$s on port %3$d.') ), $this->getName(), self::HOST, self::PORT );
|
||||
}
|
||||
|
||||
return $recommendation;
|
||||
|
||||
}
|
||||
|
||||
public function createMailEngine() {
|
||||
|
||||
$api_key = $this->options->getPostmarkApiKey();
|
||||
require_once 'PostmanPostmarkMailEngine.php';
|
||||
$engine = new PostmanPostmarkMailEngine( $api_key );
|
||||
|
||||
return $engine;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getName() {
|
||||
|
||||
return __( 'PostMark', 'post-smtp' );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getDeliveryDetails() {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PostmanWizardSocket $socket
|
||||
* @param $winningRecommendation
|
||||
* @param $userSocketOverride
|
||||
* @param $userAuthOverride
|
||||
* @return array
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function createOverrideMenu( PostmanWizardSocket $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride ) {
|
||||
|
||||
$overrideItem = parent::createOverrideMenu ( $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride );
|
||||
|
||||
// push the authentication options into the $overrideItem structure
|
||||
$overrideItem ['auth_items'] = array (
|
||||
array (
|
||||
'selected' => true,
|
||||
'name' => __ ( 'API Key', 'post-smtp' ),
|
||||
'value' => 'api_key'
|
||||
)
|
||||
);
|
||||
|
||||
return $overrideItem;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function on_admin_init() {
|
||||
|
||||
if( PostmanUtils::isAdmin() ) {
|
||||
|
||||
$this->addSettings();
|
||||
$this->registerStylesAndScripts();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function addSettings()
|
||||
{
|
||||
|
||||
add_settings_section(
|
||||
self::POSTMARK_AUTH_SECTION,
|
||||
__('Authentication', 'post-smtp'),
|
||||
array( $this, 'printPostmarkAuthSectionInfo' ),
|
||||
self::POSTMARK_AUTH_OPTIONS
|
||||
);
|
||||
|
||||
add_settings_field(
|
||||
PostmanOptions::POSTMARK_API_KEY,
|
||||
__( 'API Token', 'post-smtp' ),
|
||||
array( $this, 'postmark_api_key_callback' ),
|
||||
self::POSTMARK_AUTH_OPTIONS,
|
||||
self::POSTMARK_AUTH_SECTION
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function printPostmarkAuthSectionInfo() {
|
||||
|
||||
printf (
|
||||
'<p id="wizard_postmark_auth_help">%s</p>', sprintf ( __ ( 'Create an account at <a href="%1$s" target="_blank">%2$s</a> and enter <a href="%3$s" target="_blank">an API Token</a> below.', 'post-smtp' ),
|
||||
'https://postmarkapp.com/', 'postmarkapp.com', 'https://account.postmarkapp.com/sign_up' )
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function postmark_api_key_callback() {
|
||||
|
||||
printf ( '<input type="password" autocomplete="off" id="postmark_api_key" name="postman_options[postmark_api_key]" value="%s" size="60" class="required ps-input ps-w-75" placeholder="%s"/>', null !== $this->options->getPostmarkApiKey() ? esc_attr ( PostmanUtils::obfuscatePassword ( $this->options->getPostmarkApiKey() ) ) : '', __ ( 'Required', 'post-smtp' ) );
|
||||
print ' <input type="button" id="togglePostmarkApiKey" value="Show Password" class="button button-secondary" style="visibility:hidden" />';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function registerStylesAndScripts() {
|
||||
|
||||
$pluginData = apply_filters( 'postman_get_plugin_metadata', null );
|
||||
|
||||
wp_register_script (
|
||||
'postman-postmark',
|
||||
plugins_url ( 'Postman/Postman-Mail/postman-postmark.js', $this->rootPluginFilenameAndPath ),
|
||||
array (
|
||||
PostmanViewController::JQUERY_SCRIPT,
|
||||
'jquery_validation',
|
||||
PostmanViewController::POSTMAN_SCRIPT
|
||||
),
|
||||
$pluginData['version']
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function enqueueScript() {
|
||||
|
||||
wp_enqueue_script( 'postman-postmark' );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanTransport::getMisconfigurationMessage()
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
protected function validateTransportConfiguration() {
|
||||
$messages = parent::validateTransportConfiguration ();
|
||||
$apiKey = $this->options->getPostmarkApiKey ();
|
||||
if (empty ( $apiKey )) {
|
||||
array_push ( $messages, __ ( 'API Key can not be empty', 'post-smtp' ) . '.' );
|
||||
$this->setNotConfiguredAndReady ();
|
||||
}
|
||||
if (! $this->isSenderConfigured ()) {
|
||||
array_push ( $messages, __ ( 'Message From Address can not be empty', 'post-smtp' ) . '.' );
|
||||
$this->setNotConfiguredAndReady ();
|
||||
}
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function printWizardAuthenticationStep() {
|
||||
print '<section class="wizard_postmark">';
|
||||
$this->printPostmarkAuthSectionInfo();
|
||||
printf ( '<label for="api_key">%s</label>', __ ( 'API Key', 'post-smtp' ) );
|
||||
print '<br />';
|
||||
print $this->postmark_api_key_callback();
|
||||
print '
|
||||
<div class="postmark-documentation">
|
||||
<div>
|
||||
<iframe width="300" height="200" src="https://www.youtube.com/embed/TBQbO1Te210" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
</div>
|
||||
<div>
|
||||
<a href="https://postmansmtp.com/documentation/#configure-postmark-integration" target="_blank">Stuck in Setup?</a>
|
||||
</div>
|
||||
</div>';
|
||||
print '</section>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true, to prevent from errors because it's default Module Transport.
|
||||
*
|
||||
* @since 2.1.8
|
||||
* @version 1.0
|
||||
*/
|
||||
public function has_granted() {
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Socket's logo
|
||||
*
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getLogoURL() {
|
||||
|
||||
return POST_SMTP_ASSETS . "images/logos/postmark.png";
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
endif;
|
||||
@@ -0,0 +1,285 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
if( !class_exists( 'PostmanResendMailEngine' ) ):
|
||||
|
||||
require 'Services/Resend/Handler.php';
|
||||
|
||||
class PostmanResendMailEngine implements PostmanMailEngine {
|
||||
|
||||
protected $logger;
|
||||
|
||||
private $transcript;
|
||||
|
||||
private $api_key;
|
||||
|
||||
/**
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function __construct( $api_key ) {
|
||||
|
||||
assert( !empty( $api_key ) );
|
||||
$this->api_key = $api_key;
|
||||
|
||||
// create the logger
|
||||
$this->logger = new PostmanLogger( get_class( $this ) );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getTranscript() {
|
||||
return $this->transcript;
|
||||
}
|
||||
|
||||
private function addAttachmentsToMail( PostmanMessage $message ) {
|
||||
|
||||
$attachments = $message->getAttachments();
|
||||
if ( ! is_array( $attachments ) ) {
|
||||
// WordPress may a single filename or a newline-delimited string list of multiple filenames
|
||||
$attArray = explode( PHP_EOL, $attachments );
|
||||
} else {
|
||||
$attArray = $attachments;
|
||||
}
|
||||
// otherwise WordPress sends an array
|
||||
$attachments = array();
|
||||
foreach ( $attArray as $file ) {
|
||||
if ( ! empty( $file ) ) {
|
||||
$this->logger->debug( 'Adding attachment: ' . $file );
|
||||
|
||||
$file_name = basename( $file );
|
||||
$file_parts = explode( '.', $file_name );
|
||||
$file_type = wp_check_filetype( $file );
|
||||
$attachments[] = array(
|
||||
'content' => base64_encode( file_get_contents( $file ) ),
|
||||
'filename' => $file_name,
|
||||
'content_type' => $file_type['type'],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $attachments;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function send( PostmanMessage $message ) {
|
||||
|
||||
$options = PostmanOptions::getInstance();
|
||||
|
||||
//Resend preparation
|
||||
if ( $this->logger->isDebug() ) {
|
||||
$this->logger->debug( 'Creating Resend service with apiKey=' . $this->api_key );
|
||||
}
|
||||
|
||||
$resend = new PostmanResend( $this->api_key);
|
||||
$sender = $message->getFromAddress();
|
||||
$senderEmail = !empty( $sender->getEmail() ) ? $sender->getEmail() : $options->getMessageSenderEmail();
|
||||
$senderName = !empty( $sender->getName() ) ? $sender->getName() : $options->getMessageSenderName();
|
||||
$headers = array();
|
||||
|
||||
$sender->log( $this->logger, 'From' );
|
||||
|
||||
$sendEmail['from'] = $senderName . ' <' . $senderEmail . '>';
|
||||
|
||||
$tos = array();
|
||||
$duplicates = array();
|
||||
|
||||
// add the to recipients
|
||||
foreach ( (array)$message->getToRecipients() as $key => $recipient ) {
|
||||
|
||||
if ( !array_key_exists( $recipient->getEmail(), $duplicates ) ) {
|
||||
|
||||
if( !empty( $recipient->getName() ) ) {
|
||||
$tos[] = $recipient->getName() . ' <' . $recipient->getEmail() . '>';
|
||||
} else {
|
||||
$tos[] = $recipient->getEmail();
|
||||
}
|
||||
|
||||
$duplicates[] = $recipient->getEmail();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
$sendEmail['to'] = $tos;
|
||||
|
||||
$sendEmail['subject'] = $message->getSubject();
|
||||
|
||||
$textPart = $message->getBodyTextPart();
|
||||
if ( ! empty( $textPart ) ) {
|
||||
$this->logger->debug( 'Adding body as text' );
|
||||
$sendEmail['text'] = $textPart;
|
||||
}
|
||||
|
||||
$htmlPart = $message->getBodyHtmlPart();
|
||||
if ( ! empty( $htmlPart ) ) {
|
||||
$this->logger->debug( 'Adding body as html' );
|
||||
$sendEmail['html'] = $htmlPart;
|
||||
}
|
||||
|
||||
// add the reply-to
|
||||
$replyTo = $message->getReplyTo();
|
||||
// $replyTo is null or a PostmanEmailAddress object
|
||||
if ( isset( $replyTo ) ) {
|
||||
if( !empty( $replyTo->getName() ) ) {
|
||||
$sendEmail['reply_to'] = array( $replyTo->getName() . ' <' . $replyTo->getEmail() . '>' );
|
||||
} else {
|
||||
$sendEmail['reply_to'] = array( $replyTo->getEmail() );
|
||||
}
|
||||
}
|
||||
|
||||
// add the Postman signature - append it to whatever the user may have set
|
||||
if ( ! $options->isStealthModeEnabled() ) {
|
||||
$pluginData = apply_filters( 'postman_get_plugin_metadata', null );
|
||||
$headers['X-Mailer'] = sprintf( 'Postman SMTP %s for WordPress (%s)', $pluginData ['version'], 'https://wordpress.org/plugins/post-smtp/' );
|
||||
}
|
||||
|
||||
foreach ( ( array ) $message->getHeaders() as $header ) {
|
||||
$this->logger->debug( sprintf( 'Adding user header %s=%s', $header ['name'], $header ['content'] ) );
|
||||
$headers[$header['name']] = $header ['content'];
|
||||
}
|
||||
|
||||
// add the messageId
|
||||
$messageId = $message->getMessageId();
|
||||
if ( ! empty( $messageId ) ) {
|
||||
$headers['message-id'] = $messageId;
|
||||
}
|
||||
|
||||
if( !empty( $headers ) ) {
|
||||
$sendEmail['headers'] = $headers;
|
||||
}
|
||||
|
||||
// if the caller set a Content-Type header, use it
|
||||
$contentType = $message->getContentType();
|
||||
if ( ! empty( $contentType ) ) {
|
||||
$this->logger->debug( 'Some header keys are reserved. You may not include any of the following reserved headers: x-sg-id, x-sg-eid, received, dkim-signature, Content-Type, Content-Transfer-Encoding, To, From, Subject, Reply-To, CC, BCC.' );
|
||||
}
|
||||
|
||||
$cc = array();
|
||||
$duplicates = array();
|
||||
foreach ( ( array ) $message->getCcRecipients() as $recipient ) {
|
||||
|
||||
if ( ! in_array( $recipient->getEmail(), $duplicates ) ) {
|
||||
|
||||
$recipient->log($this->logger, 'Cc');
|
||||
if( !empty( $recipient->getName() ) ) {
|
||||
$cc[] = $recipient->getName() . ' <' . $recipient->getEmail() . '>';
|
||||
} else {
|
||||
$cc[] = $recipient->getEmail();
|
||||
}
|
||||
|
||||
$duplicates[] = $recipient->getEmail();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
if( !empty( $cc ) ) {
|
||||
$sendEmail['cc'] = $cc;
|
||||
}
|
||||
|
||||
$bcc = array();
|
||||
$duplicates = array();
|
||||
foreach ( ( array ) $message->getBccRecipients() as $recipient ) {
|
||||
|
||||
if ( ! in_array( $recipient->getEmail(), $duplicates ) ) {
|
||||
|
||||
$recipient->log($this->logger, 'Bcc');
|
||||
if( !empty( $recipient->getName() ) ) {
|
||||
$bcc[] = $recipient->getName() . ' <' . $recipient->getEmail() . '>';
|
||||
} else {
|
||||
$bcc[] = $recipient->getEmail();
|
||||
}
|
||||
|
||||
$duplicates[] = $recipient->getEmail();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if( !empty( $bcc ) ) {
|
||||
$sendEmail['bcc'] = $bcc;
|
||||
}
|
||||
|
||||
// add attachments
|
||||
$this->logger->debug( 'Adding attachments' );
|
||||
|
||||
$attachments = $this->addAttachmentsToMail( $message );
|
||||
|
||||
if( !empty( $attachments ) ) {
|
||||
$sendEmail['attachments'] = $attachments;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
// send the message
|
||||
if ( $this->logger->isDebug() ) {
|
||||
$this->logger->debug( 'Sending mail' );
|
||||
}
|
||||
|
||||
$response = $resend->send( $sendEmail );
|
||||
|
||||
$this->transcript = print_r( $response, true );
|
||||
$this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
|
||||
$this->transcript .= print_r( $sendEmail, true );
|
||||
$this->logger->debug( 'Transcript=' . $this->transcript );
|
||||
|
||||
} catch (Exception $e) {
|
||||
|
||||
$this->transcript = $e->getMessage();
|
||||
$this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
|
||||
$this->transcript .= print_r( $sendEmail, true );
|
||||
$this->logger->debug( 'Transcript=' . $this->transcript );
|
||||
|
||||
throw $e;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
private function errorCodesMap( $error_code ) {
|
||||
switch ( $error_code ) {
|
||||
case 400:
|
||||
$message = sprintf( __( 'ERROR: Request is invalid. Check the error code in JSON. Status code is %1$s', 'post-smtp' ), $error_code );
|
||||
break;
|
||||
case 401:
|
||||
$message = sprintf( __( 'ERROR: You have not been authenticated. Make sure the provided api-key is correct. Status code is %1$s', 'post-smtp' ), $error_code );
|
||||
break;
|
||||
case 402:
|
||||
$message = sprintf( __( 'ERROR: Make sure you\'re account is activated and that you\'ve sufficient credits. Status code is %1$s', 'post-smtp' ), $error_code );
|
||||
break;
|
||||
case 403:
|
||||
$message = sprintf( __( 'ERROR: Forbidden. Make sure you have proper permissions. Status code is %1$s', 'post-smtp' ), $error_code );
|
||||
break;
|
||||
case 404:
|
||||
$message = sprintf( __( 'ERROR: Resource not found. Status code is %1$s', 'post-smtp' ), $error_code );
|
||||
break;
|
||||
case 422:
|
||||
$message = sprintf( __( 'ERROR: Validation Error. Check your input data. Status code is %1$s', 'post-smtp' ), $error_code );
|
||||
break;
|
||||
case 429:
|
||||
$message = sprintf( __( 'ERROR: Too many requests. You have exceeded the rate limit. Status code is %1$s', 'post-smtp' ), $error_code );
|
||||
break;
|
||||
case 500:
|
||||
$message = sprintf( __( 'ERROR: Internal server error. Please try again later. Status code is %1$s', 'post-smtp' ), $error_code );
|
||||
break;
|
||||
default:
|
||||
$message = sprintf( __( 'ERROR: An unknown error occurred. Status code is %1$s', 'post-smtp' ), $error_code );
|
||||
break;
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
}
|
||||
endif;
|
||||
@@ -0,0 +1,309 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
require_once 'PostmanModuleTransport.php';
|
||||
|
||||
/**
|
||||
* Postman Resend Transport
|
||||
*
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
if( !class_exists( 'PostmanResendTransport' ) ):
|
||||
class PostmanResendTransport extends PostmanAbstractModuleTransport implements PostmanModuleTransport {
|
||||
|
||||
const SLUG = 'resend_api';
|
||||
const PORT = 443;
|
||||
const HOST = 'api.resend.com';
|
||||
const PRIORITY = 49000;
|
||||
const RESEND_AUTH_OPTIONS = 'postman_resend_auth_options';
|
||||
const RESEND_AUTH_SECTION = 'postman_resend_auth_section';
|
||||
|
||||
/**
|
||||
* PostmanResendTransport constructor.
|
||||
* @param $rootPluginFilenameAndPath
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function __construct( $rootPluginFilenameAndPath ) {
|
||||
|
||||
parent::__construct( $rootPluginFilenameAndPath );
|
||||
|
||||
// add a hook on the plugins_loaded event
|
||||
add_action( 'admin_init', array( $this, 'on_admin_init' ) );
|
||||
|
||||
}
|
||||
|
||||
public function getProtocol() {
|
||||
return 'https';
|
||||
}
|
||||
|
||||
// this should be standard across all transports
|
||||
public function getSlug() {
|
||||
return self::SLUG;
|
||||
}
|
||||
|
||||
public function getName() {
|
||||
return __( 'Resend API', 'post-smtp' );
|
||||
}
|
||||
|
||||
/**
|
||||
* v0.2.1
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getHostname() {
|
||||
return self::HOST;
|
||||
}
|
||||
|
||||
/**
|
||||
* v0.2.1
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getPort() {
|
||||
return self::PORT;
|
||||
}
|
||||
|
||||
/**
|
||||
* v1.7.0
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTransportType() {
|
||||
return 'resend_api';
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getConfigurationBid( PostmanWizardSocket $hostData, $userAuthOverride, $originalSmtpServer ) {
|
||||
|
||||
$recommendation = array();
|
||||
$recommendation ['priority'] = 0;
|
||||
$recommendation ['transport'] = self::SLUG;
|
||||
$recommendation ['hostname'] = null; // scribe looks this
|
||||
$recommendation ['label'] = $this->getName();
|
||||
$recommendation['logo_url'] = $this->getLogoURL();
|
||||
|
||||
if ($hostData->hostname == self::HOST && $hostData->port == self::PORT) {
|
||||
$recommendation ['priority'] = self::PRIORITY;
|
||||
/* translators: where variables are (1) transport name (2) host and (3) port */
|
||||
$recommendation ['message'] = sprintf ( __ ( ('Postman recommends the %1$s to host %2$s on port %3$d.') ), $this->getName(), self::HOST, self::PORT );
|
||||
}
|
||||
|
||||
return $recommendation;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function createMailEngine() {
|
||||
|
||||
$api_key = $this->options->getResendApiKey();
|
||||
require_once 'PostmanResendMailEngine.php';
|
||||
$engine = new PostmanResendMailEngine( $api_key );
|
||||
|
||||
return $engine;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getDeliveryDetails() {
|
||||
/* translators: where (1) is the secure icon and (2) is the transport name */
|
||||
return sprintf ( __ ( 'Postman will send mail via the <b>%1$s %2$s</b>.', 'post-smtp' ), '🔐', $this->getName () );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PostmanWizardSocket $socket
|
||||
* @param $winningRecommendation
|
||||
* @param $userSocketOverride
|
||||
* @param $userAuthOverride
|
||||
* @return array
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function populateConfiguration( $hostname ) {
|
||||
|
||||
$response = parent::populateConfiguration( $hostname );
|
||||
$response [PostmanOptions::TRANSPORT_TYPE] = $this->getSlug();
|
||||
$response [PostmanOptions::PORT] = $this->getPort();
|
||||
$response [PostmanOptions::HOSTNAME] = $this->getHostname();
|
||||
$response [PostmanOptions::SECURITY_TYPE] = PostmanOptions::SECURITY_TYPE_SMTPS;
|
||||
$response [PostmanOptions::AUTHENTICATION_TYPE] = PostmanOptions::AUTHENTICATION_TYPE_OAUTH2;
|
||||
|
||||
return $response;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function on_admin_init() {
|
||||
$this->addSettings();
|
||||
$this->registerStylesAndScripts();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function addSettings()
|
||||
{
|
||||
|
||||
add_settings_section(
|
||||
self::RESEND_AUTH_SECTION,
|
||||
__('Authentication', 'post-smtp'),
|
||||
array( $this, 'printResendAuthSectionInfo' ),
|
||||
self::RESEND_AUTH_OPTIONS
|
||||
);
|
||||
|
||||
add_settings_field(
|
||||
PostmanOptions::RESEND_API_KEY,
|
||||
__( 'API Key', 'post-smtp' ),
|
||||
array( $this, 'resend_api_key_callback' ),
|
||||
self::RESEND_AUTH_OPTIONS,
|
||||
self::RESEND_AUTH_SECTION
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function printResendAuthSectionInfo() {
|
||||
|
||||
printf (
|
||||
'<p id="wizard_resend_auth_help">%s</p>', sprintf ( __ ( 'Create an account at <a href="%1$s" target="_blank">%2$s</a> and enter <a href="%3$s" target="_blank">an API key</a> below.', 'post-smtp' ),
|
||||
'https://resend.com/', 'resend.com', 'https://resend.com/api-keys' )
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function resend_api_key_callback() {
|
||||
|
||||
printf(
|
||||
'<input type="password" autocomplete="off" id="resend_api_key" name="postman_options[resend_api_key]" value="%s" size="60" class="required ps-input ps-w-75" placeholder="%s"/>',
|
||||
null !== $this->options->getResendApiKey() ? esc_attr( PostmanUtils::obfuscatePassword( $this->options->getResendApiKey() ) ) : '',
|
||||
__( 'Required', 'post-smtp' )
|
||||
);
|
||||
print ' <input type="button" id="toggleResendApiKey" value="Show Password" class="button button-secondary" style="visibility:hidden" />';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function registerStylesAndScripts() {
|
||||
|
||||
// register the stylesheet and javascript external resources
|
||||
$pluginData = apply_filters ( 'postman_get_plugin_metadata', null );
|
||||
wp_register_script (
|
||||
'postman-resend',
|
||||
plugins_url ( 'Postman/Postman-Mail/postman-resend.js', $this->rootPluginFilenameAndPath ),
|
||||
array (
|
||||
PostmanViewController::JQUERY_SCRIPT,
|
||||
'jquery_validation',
|
||||
PostmanViewController::POSTMAN_SCRIPT
|
||||
),
|
||||
$pluginData['version']
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function enqueueScript() {
|
||||
|
||||
wp_enqueue_script( 'postman-resend' );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function printWizardAuthenticationStep() {
|
||||
print '<section class="wizard_resend">';
|
||||
$this->printResendAuthSectionInfo();
|
||||
printf ( '<label for="api_key">%s</label>', __ ( 'API Key', 'post-smtp' ) );
|
||||
print '<br />';
|
||||
print $this->resend_api_key_callback();
|
||||
print '</section>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Resend's logo
|
||||
*
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getLogoURL() {
|
||||
|
||||
return POST_SMTP_ASSETS . "images/logos/resend.png";
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true, to prevent from errors because it's default Module Transport.
|
||||
*
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function has_granted() {
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanTransport::getMisconfigurationMessage()
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
protected function validateTransportConfiguration() {
|
||||
$messages = parent::validateTransportConfiguration ();
|
||||
$apiKey = $this->options->getResendApiKey ();
|
||||
if (empty ( $apiKey )) {
|
||||
array_push ( $messages, __ ( 'API Key can not be empty', 'post-smtp' ) . '.' );
|
||||
$this->setNotConfiguredAndReady ();
|
||||
}
|
||||
if (! $this->isSenderConfigured ()) {
|
||||
array_push ( $messages, __ ( 'Message From Address can not be empty', 'post-smtp' ) . '.' );
|
||||
$this->setNotConfiguredAndReady ();
|
||||
}
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mixed $data
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function prepareOptionsForExport($data) {
|
||||
$data = parent::prepareOptionsForExport ( $data );
|
||||
$data [PostmanOptions::RESEND_API_KEY] = PostmanOptions::getInstance ()->getResendApiKey ();
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
endif;
|
||||
@@ -0,0 +1,276 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'PostmanSendGridMailEngine' ) ) {
|
||||
|
||||
require_once 'Services/SendGrid/Handler.php';
|
||||
|
||||
/**
|
||||
* Sends mail with the SendGrid API
|
||||
* https://sendgrid.com/docs/API_Reference/Web_API/mail.html
|
||||
*
|
||||
* @author jasonhendriks
|
||||
*/
|
||||
class PostmanSendGridMailEngine implements PostmanMailEngine {
|
||||
|
||||
// logger for all concrete classes - populate with setLogger($logger)
|
||||
protected $logger;
|
||||
|
||||
// the result
|
||||
private $transcript;
|
||||
|
||||
private $apiKey;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mixed $senderEmail
|
||||
* @param mixed $accessToken
|
||||
*/
|
||||
function __construct( $apiKey ) {
|
||||
assert( ! empty( $apiKey ) );
|
||||
$this->apiKey = $apiKey;
|
||||
|
||||
// create the logger
|
||||
$this->logger = new PostmanLogger( get_class( $this ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanSmtpEngine::send()
|
||||
*/
|
||||
public function send( PostmanMessage $message ) {
|
||||
$options = PostmanOptions::getInstance();
|
||||
|
||||
$sendgrid = new PostmanSendGrid( $this->apiKey );
|
||||
$content = array();
|
||||
$recipients = array();
|
||||
$headers = array();
|
||||
|
||||
// add the From Header
|
||||
$sender = $message->getFromAddress();
|
||||
|
||||
$senderEmail = ! empty( $sender->getEmail() ) ? $sender->getEmail() : $options->getMessageSenderEmail();
|
||||
$senderName = ! empty( $sender->getName() ) ? $sender->getName() : $options->getMessageSenderName();
|
||||
|
||||
$content['from'] = array(
|
||||
'email' => $senderEmail,
|
||||
'name' => $senderName
|
||||
);
|
||||
|
||||
// now log it
|
||||
$sender->log( $this->logger, 'From' );
|
||||
|
||||
$duplicates = array();
|
||||
|
||||
// add the to recipients
|
||||
foreach ( ( array ) $message->getToRecipients() as $recipient ) {
|
||||
if ( ! in_array( $recipient->getEmail(), $duplicates ) ) {
|
||||
$name = $recipient->getName();
|
||||
if ( ! is_string( $name ) || $name === null ) {
|
||||
$name = '';
|
||||
}
|
||||
$content['personalizations'][0]['to'][] = array(
|
||||
'email' => $recipient->getEmail(),
|
||||
'name' => $name
|
||||
);
|
||||
$duplicates[] = $recipient->getEmail();
|
||||
}
|
||||
}
|
||||
|
||||
// add the subject
|
||||
if ( null !== $message->getSubject() ) {
|
||||
|
||||
$content['subject'] = $message->getSubject();
|
||||
|
||||
}
|
||||
|
||||
// add the message content
|
||||
|
||||
$textPart = $message->getBodyTextPart();
|
||||
if ( ! empty( $textPart ) ) {
|
||||
|
||||
$this->logger->debug( 'Adding body as text' );
|
||||
|
||||
$content['content'] = array(
|
||||
array(
|
||||
'value' => $textPart,
|
||||
'type' => 'text/plain',
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
$htmlPart = $message->getBodyHtmlPart();
|
||||
if ( ! empty( $htmlPart ) ) {
|
||||
|
||||
$this->logger->debug( 'Adding body as html' );
|
||||
|
||||
$content['content'] = array(
|
||||
array(
|
||||
'value' => $htmlPart,
|
||||
'type' => 'text/html',
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
}
|
||||
|
||||
// add the reply-to
|
||||
$replyTo = $message->getReplyTo();
|
||||
// $replyTo is null or a PostmanEmailAddress object
|
||||
if ( isset( $replyTo ) ) {
|
||||
|
||||
$content['reply_to'] = array(
|
||||
'email' => $replyTo->getEmail(),
|
||||
'name' => $replyTo->getName()
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
// add the Postman signature - append it to whatever the user may have set
|
||||
if ( ! $options->isStealthModeEnabled() ) {
|
||||
$pluginData = apply_filters( 'postman_get_plugin_metadata', null );
|
||||
//$email->addHeader( 'X-Mailer', sprintf( 'Postman SMTP %s for WordPress (%s)', $pluginData ['version'], 'https://wordpress.org/plugins/post-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'] ) );
|
||||
$headers[$header ['name']] = $header['content'];
|
||||
}
|
||||
|
||||
// if the caller set a Content-Type header, use it
|
||||
$contentType = $message->getContentType();
|
||||
if ( ! empty( $contentType ) ) {
|
||||
$this->logger->debug( 'Some header keys are reserved. You may not include any of the following reserved headers: x-sg-id, x-sg-eid, received, dkim-signature, Content-Type, Content-Transfer-Encoding, To, From, Subject, Reply-To, CC, BCC.' );
|
||||
}
|
||||
|
||||
// add the cc recipients
|
||||
$ccEmails = array();
|
||||
foreach ( ( array ) $message->getCcRecipients() as $recipient ) {
|
||||
|
||||
if ( ! in_array( $recipient->getEmail(), $duplicates ) ) {
|
||||
|
||||
$recipient->log($this->logger, 'Cc');
|
||||
$content['personalizations'][0]['cc'][] = array(
|
||||
'email' => $recipient->getEmail(),
|
||||
'name' => $recipient->getName()
|
||||
);
|
||||
|
||||
$duplicates[] = $recipient->getEmail();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// add the bcc recipients
|
||||
$bccEmails = array();
|
||||
foreach ( ( array ) $message->getBccRecipients() as $recipient ) {
|
||||
|
||||
if ( ! in_array( $recipient->getEmail(), $duplicates ) ) {
|
||||
|
||||
$recipient->log($this->logger, 'Bcc');
|
||||
$content['personalizations'][0]['bcc'][] = array(
|
||||
'email' => $recipient->getEmail(),
|
||||
'name' => $recipient->getName()
|
||||
);
|
||||
|
||||
$duplicates[] = $recipient->getEmail();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
if( !empty( $headers ) ){
|
||||
$content['headers'] = $headers;
|
||||
}
|
||||
|
||||
// add the messageId
|
||||
$messageId = '<' . $message->getMessageId() . '>';
|
||||
if ( ! empty( $messageId ) ) {
|
||||
//$email->addHeader( 'message-id', $messageId );
|
||||
}
|
||||
|
||||
// add attachments
|
||||
$this->logger->debug( 'Adding attachments' );
|
||||
|
||||
$attachments = $this->addAttachmentsToMail( $message );
|
||||
|
||||
if( !empty( $attachments ) ) {
|
||||
|
||||
$content['attachments'] = $this->addAttachmentsToMail( $message );
|
||||
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
|
||||
// send the message
|
||||
if ( $this->logger->isDebug() ) {
|
||||
$this->logger->debug( 'Sending mail' );
|
||||
}
|
||||
|
||||
$response = $sendgrid->send( $content );
|
||||
$this->transcript = print_r( $response, true );
|
||||
$this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
|
||||
$this->transcript .= print_r( $content, true );
|
||||
$this->logger->debug( 'Transcript=' . $this->transcript );
|
||||
|
||||
} catch ( Exception $e ) {
|
||||
|
||||
$this->transcript = $e->getMessage();
|
||||
$this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
|
||||
$this->transcript .= print_r( $content, true );
|
||||
$this->logger->debug( 'Transcript=' . $this->transcript );
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add attachments to the message
|
||||
*
|
||||
* @param Postman_Zend_Mail $mail
|
||||
*/
|
||||
private function addAttachmentsToMail( PostmanMessage $message ) {
|
||||
$attachments = $message->getAttachments();
|
||||
if ( ! is_array( $attachments ) ) {
|
||||
// WordPress may a single filename or a newline-delimited string list of multiple filenames
|
||||
$attArray = explode( PHP_EOL, $attachments );
|
||||
} else {
|
||||
$attArray = $attachments;
|
||||
}
|
||||
// otherwise WordPress sends an array
|
||||
$attachments = array();
|
||||
foreach ( $attArray as $file ) {
|
||||
if ( ! empty( $file ) ) {
|
||||
$this->logger->debug( 'Adding attachment: ' . $file );
|
||||
$file_name = basename( $file );
|
||||
$file_type = wp_check_filetype( $file );
|
||||
$type = $file_type['type'];
|
||||
if ( !is_string( $type) || empty( $type ) ) {
|
||||
$type = 'application/octet-stream';
|
||||
}
|
||||
$attachments[] = array(
|
||||
'content' => base64_encode( file_get_contents( $file ) ),
|
||||
'type' => $type,
|
||||
'filename' => $file_name,
|
||||
'disposition' => 'attachment',
|
||||
// 'name' removed for SendGrid API compatibility
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $attachments;
|
||||
}
|
||||
|
||||
// return the SMTP session transcript
|
||||
public function getTranscript() {
|
||||
return $this->transcript;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,285 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
require_once 'PostmanModuleTransport.php';
|
||||
/**
|
||||
* Postman SendGrid module
|
||||
*
|
||||
* @author jasonhendriks
|
||||
*
|
||||
*/
|
||||
class PostmanSendGridTransport extends PostmanAbstractModuleTransport implements PostmanModuleTransport {
|
||||
const SLUG = 'sendgrid_api';
|
||||
const PORT = 443;
|
||||
const HOST = 'api.sendgrid.com';
|
||||
const PRIORITY = 48000;
|
||||
const SENDGRID_AUTH_OPTIONS = 'postman_sendgrid_auth_options';
|
||||
const SENDGRID_AUTH_SECTION = 'postman_sendgrid_auth_section';
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mixed $rootPluginFilenameAndPath
|
||||
*/
|
||||
public function __construct($rootPluginFilenameAndPath) {
|
||||
parent::__construct ( $rootPluginFilenameAndPath );
|
||||
|
||||
// add a hook on the plugins_loaded event
|
||||
add_action ( 'admin_init', array (
|
||||
$this,
|
||||
'on_admin_init'
|
||||
) );
|
||||
}
|
||||
public function getProtocol() {
|
||||
return 'https';
|
||||
}
|
||||
|
||||
// this should be standard across all transports
|
||||
public function getSlug() {
|
||||
return self::SLUG;
|
||||
}
|
||||
public function getName() {
|
||||
return __ ( 'SendGrid API', 'post-smtp' );
|
||||
}
|
||||
/**
|
||||
* v0.2.1
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getHostname() {
|
||||
return self::HOST;
|
||||
}
|
||||
/**
|
||||
* v0.2.1
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getPort() {
|
||||
return self::PORT;
|
||||
}
|
||||
/**
|
||||
* v1.7.0
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTransportType() {
|
||||
return 'SendGrid_api';
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanModuleTransport::createMailEngine()
|
||||
*/
|
||||
public function createMailEngine() {
|
||||
$apiKey = $this->options->getSendGridApiKey ();
|
||||
require_once 'PostmanSendGridMailEngine.php';
|
||||
$engine = new PostmanSendGridMailEngine ( $apiKey );
|
||||
return $engine;
|
||||
}
|
||||
public function getDeliveryDetails() {
|
||||
/* translators: where (1) is the secure icon and (2) is the transport name */
|
||||
return sprintf ( __ ( 'Postman will send mail via the <b>%1$s %2$s</b>.', 'post-smtp' ), '🔐', $this->getName () );
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mixed $data
|
||||
*/
|
||||
public function prepareOptionsForExport($data) {
|
||||
$data = parent::prepareOptionsForExport ( $data );
|
||||
$data [PostmanOptions::SENDGRID_API_KEY] = PostmanOptions::getInstance ()->getSendGridApiKey ();
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanTransport::getMisconfigurationMessage()
|
||||
*/
|
||||
protected function validateTransportConfiguration() {
|
||||
$messages = parent::validateTransportConfiguration ();
|
||||
$apiKey = $this->options->getSendGridApiKey ();
|
||||
if (empty ( $apiKey )) {
|
||||
array_push ( $messages, __ ( 'API Key can not be empty', 'post-smtp' ) . '.' );
|
||||
$this->setNotConfiguredAndReady ();
|
||||
}
|
||||
if (! $this->isSenderConfigured ()) {
|
||||
array_push ( $messages, __ ( 'Message From Address can not be empty', 'post-smtp' ) . '.' );
|
||||
$this->setNotConfiguredAndReady ();
|
||||
}
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanModuleTransport::getConfigurationBid()
|
||||
*/
|
||||
public function getConfigurationBid(PostmanWizardSocket $hostData, $userAuthOverride, $originalSmtpServer) {
|
||||
$recommendation = array ();
|
||||
$recommendation ['priority'] = 0;
|
||||
$recommendation ['transport'] = self::SLUG;
|
||||
$recommendation ['hostname'] = null; // scribe looks this
|
||||
$recommendation ['label'] = $this->getName ();
|
||||
$recommendation['logo_url'] = $this->getLogoURL();
|
||||
|
||||
if ($hostData->hostname == self::HOST && $hostData->port == self::PORT) {
|
||||
$recommendation ['priority'] = self::PRIORITY;
|
||||
/* translators: where variables are (1) transport name (2) host and (3) port */
|
||||
$recommendation ['message'] = sprintf ( __ ( ('Postman recommends the %1$s to host %2$s on port %3$d.') ), $this->getName (), self::HOST, self::PORT );
|
||||
}
|
||||
return $recommendation;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mixed $hostname
|
||||
* @param mixed $response
|
||||
*/
|
||||
public function populateConfiguration($hostname) {
|
||||
$response = parent::populateConfiguration ( $hostname );
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function createOverrideMenu(PostmanWizardSocket $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride) {
|
||||
$overrideItem = parent::createOverrideMenu ( $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride );
|
||||
// push the authentication options into the $overrideItem structure
|
||||
$overrideItem ['auth_items'] = array (
|
||||
array (
|
||||
'selected' => true,
|
||||
'name' => __ ( 'API Key', 'post-smtp' ),
|
||||
'value' => 'api_key'
|
||||
)
|
||||
);
|
||||
return $overrideItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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->addSettings ();
|
||||
$this->registerStylesAndScripts ();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* What follows in the code responsible for creating the Admin Settings page
|
||||
*/
|
||||
|
||||
/**
|
||||
*/
|
||||
public function addSettings() {
|
||||
// the SendGrid Auth section
|
||||
add_settings_section ( PostmanSendGridTransport::SENDGRID_AUTH_SECTION, __ ( 'Authentication', 'post-smtp' ), array (
|
||||
$this,
|
||||
'printSendGridAuthSectionInfo'
|
||||
), PostmanSendGridTransport::SENDGRID_AUTH_OPTIONS );
|
||||
|
||||
add_settings_field ( PostmanOptions::SENDGRID_API_KEY, __ ( 'API Key', 'post-smtp' ), array (
|
||||
$this,
|
||||
'sendgrid_api_key_callback'
|
||||
), PostmanSendGridTransport::SENDGRID_AUTH_OPTIONS, PostmanSendGridTransport::SENDGRID_AUTH_SECTION );
|
||||
|
||||
add_settings_field(
|
||||
PostmanOptions::SENDGRID_REGION,
|
||||
__( 'Region', 'post-smtp' ),
|
||||
array( $this, 'sendgrid_region_callback' ),
|
||||
PostmanSendGridTransport::SENDGRID_AUTH_OPTIONS,
|
||||
PostmanSendGridTransport::SENDGRID_AUTH_SECTION
|
||||
);
|
||||
|
||||
}
|
||||
public function printSendGridAuthSectionInfo() {
|
||||
/* Translators: Where (1) is the service URL and (2) is the service name and (3) is a api key URL */
|
||||
printf ( '<p id="wizard_sendgrid_auth_help">%s</p>', sprintf ( __ ( 'Create an account at <a href="%1$s" target="_blank">%2$s</a> and enter <a href="%3$s" target="_blank">an API key</a> below.', 'post-smtp' ), 'https://sendgrid.com', 'SendGrid.com', 'https://app.sendgrid.com/settings/api_keys' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function sendgrid_api_key_callback() {
|
||||
printf ( '<input type="password" autocomplete="off" id="sendgrid_api_key" name="postman_options[sendgrid_api_key]" value="%s" size="60" class="required ps-input ps-w-75" placeholder="%s"/>', null !== $this->options->getSendGridApiKey () ? esc_attr ( PostmanUtils::obfuscatePassword ( $this->options->getSendGridApiKey () ) ) : '', __ ( 'Required', 'post-smtp' ) );
|
||||
print ' <input type="button" id="toggleSendGridApiKey" value="Show Password" class="button button-secondary" style="visibility:hidden" />';
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the SendGrid region selection dropdown.
|
||||
*
|
||||
* Outputs a select box for users to choose the SendGrid region (Global or EU).
|
||||
*
|
||||
* @since 3.1.0
|
||||
* @version 1.0.0
|
||||
*/
|
||||
public function sendgrid_region_callback() {
|
||||
$options = get_option( PostmanOptions::POSTMAN_OPTIONS );
|
||||
$selected_region = isset( $options[ PostmanOptions::SENDGRID_REGION ] ) ? $options[ PostmanOptions::SENDGRID_REGION ] : 'Global';
|
||||
|
||||
echo '<select name="postman_options[' . esc_attr( PostmanOptions::SENDGRID_REGION ) . ']">';
|
||||
echo '<option value="Global"' . selected( $selected_region, 'Global', false ) . '>' . __( 'Global', 'post-smtp' ) . '</option>';
|
||||
echo '<option value="EU"' . selected( $selected_region, 'EU', false ) . '>' . __( 'Europe (EU)', 'post-smtp' ) . '</option>';
|
||||
echo '</select>';
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function registerStylesAndScripts() {
|
||||
// register the stylesheet and javascript external resources
|
||||
$pluginData = apply_filters ( 'postman_get_plugin_metadata', null );
|
||||
wp_register_script ( 'postman_sendgrid_script', plugins_url ( 'Postman/Postman-Mail/postman_sendgrid.js', $this->rootPluginFilenameAndPath ), array (
|
||||
PostmanViewController::JQUERY_SCRIPT,
|
||||
'jquery_validation',
|
||||
PostmanViewController::POSTMAN_SCRIPT
|
||||
), $pluginData ['version'] );
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function enqueueScript() {
|
||||
wp_enqueue_script ( 'postman_sendgrid_script' );
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function printWizardAuthenticationStep() {
|
||||
print '<section class="wizard_sendgrid">';
|
||||
$this->printSendGridAuthSectionInfo ();
|
||||
printf ( '<label for="api_key">%s</label>', __ ( 'API Key', 'post-smtp' ) );
|
||||
print '<br />';
|
||||
print $this->sendgrid_api_key_callback ();
|
||||
print '</section>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Socket's logo
|
||||
*
|
||||
* @since 2.1
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getLogoURL() {
|
||||
|
||||
return POST_SMTP_ASSETS . "images/logos/sendgrid.png";
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns true, to prevent from errors because it's default Module Transport.
|
||||
*
|
||||
* @since 2.1.8
|
||||
* @version 1.0
|
||||
*/
|
||||
public function has_granted() {
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,313 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
if( !class_exists( 'PostmanSendinblueMailEngine' ) ):
|
||||
|
||||
require 'Services/Sendinblue/Handler.php';
|
||||
|
||||
class PostmanSendinblueMailEngine implements PostmanMailEngine {
|
||||
|
||||
protected $logger;
|
||||
|
||||
private $transcript;
|
||||
|
||||
private $api_key;
|
||||
|
||||
|
||||
/**
|
||||
* @since 2.1
|
||||
* @version 1.0
|
||||
*/
|
||||
public function __construct( $api_key ) {
|
||||
|
||||
assert( !empty( $api_key ) );
|
||||
$this->api_key = $api_key;
|
||||
|
||||
// create the logger
|
||||
$this->logger = new PostmanLogger( get_class( $this ) );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.1
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getTranscript() {
|
||||
return $this->transcript;
|
||||
}
|
||||
|
||||
private function addAttachmentsToMail( PostmanMessage $message ) {
|
||||
|
||||
$attachments = $message->getAttachments();
|
||||
if ( ! is_array( $attachments ) ) {
|
||||
// WordPress may a single filename or a newline-delimited string list of multiple filenames
|
||||
$attArray = explode( PHP_EOL, $attachments );
|
||||
} else {
|
||||
$attArray = $attachments;
|
||||
}
|
||||
// otherwise WordPress sends an array
|
||||
$attachments = array();
|
||||
foreach ( $attArray as $file ) {
|
||||
if ( ! empty( $file ) ) {
|
||||
$this->logger->debug( 'Adding attachment: ' . $file );
|
||||
|
||||
$file_name = basename( $file );
|
||||
$file_parts = explode( '.', $file_name );
|
||||
$file_type = wp_check_filetype( $file );
|
||||
$attachments[] = array(
|
||||
'content' => base64_encode( file_get_contents( $file ) ),
|
||||
'type' => $file_type['type'],
|
||||
'file_name' => $file_name,
|
||||
'disposition' => 'attachment',
|
||||
'id' => $file_parts[0],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $attachments;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.1
|
||||
* @version 1.0
|
||||
*/
|
||||
public function send( PostmanMessage $message ) {
|
||||
|
||||
$options = PostmanOptions::getInstance();
|
||||
//Sendinblue preparation
|
||||
if ( $this->logger->isDebug() ) {
|
||||
|
||||
$this->logger->debug( 'Creating SendGrid service with apiKey=' . $this->apiKey );
|
||||
|
||||
}
|
||||
|
||||
$sendinblue = new PostmanSendinblue( $this->api_key);
|
||||
$sender = $message->getFromAddress();
|
||||
$senderEmail = !empty( $sender->getEmail() ) ? $sender->getEmail() : $options->getMessageSenderEmail();
|
||||
$senderName = !empty( $sender->getName() ) ? $sender->getName() : $options->getMessageSenderName();
|
||||
$headers = array();
|
||||
|
||||
$sender->log( $this->logger, 'From' );
|
||||
|
||||
$sendSmtpEmail['sender'] = array(
|
||||
'name' => $senderName,
|
||||
'email' => $senderEmail
|
||||
);
|
||||
|
||||
$tos = array();
|
||||
$duplicates = array();
|
||||
|
||||
// add the to recipients
|
||||
foreach ( (array)$message->getToRecipients() as $key => $recipient ) {
|
||||
|
||||
if ( !array_key_exists( $recipient->getEmail(), $duplicates ) ) {
|
||||
|
||||
$tos[] = array(
|
||||
'email' => $recipient->getEmail()
|
||||
);
|
||||
|
||||
if( !empty( $recipient->getName() ) ) {
|
||||
|
||||
$tos[$key]['name'] = $recipient->getName();
|
||||
|
||||
}
|
||||
|
||||
$duplicates[] = $recipient->getEmail();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
$sendSmtpEmail['to'] = $tos;
|
||||
|
||||
$sendSmtpEmail['subject'] = $message->getSubject();
|
||||
|
||||
$textPart = $message->getBodyTextPart();
|
||||
if ( ! empty( $textPart ) ) {
|
||||
$this->logger->debug( 'Adding body as text' );
|
||||
$sendSmtpEmail['textContent'] = $textPart;
|
||||
}
|
||||
|
||||
$htmlPart = $message->getBodyHtmlPart();
|
||||
if ( ! empty( $htmlPart ) ) {
|
||||
$this->logger->debug( 'Adding body as html' );
|
||||
$sendSmtpEmail['htmlContent'] = $htmlPart;
|
||||
}
|
||||
|
||||
// add the reply-to
|
||||
$replyTo = $message->getReplyTo();
|
||||
// $replyTo is null or a PostmanEmailAddress object
|
||||
if ( isset( $replyTo ) ) {
|
||||
$sendSmtpEmail['replyTo'] = array(
|
||||
'email' => $replyTo->getEmail()
|
||||
);
|
||||
|
||||
if( !empty( $replyTo->getName() ) ) {
|
||||
$sendSmtpEmail['name'] = $replyTo->getName();
|
||||
}
|
||||
}
|
||||
|
||||
// add the Postman signature - append it to whatever the user may have set
|
||||
if ( ! $options->isStealthModeEnabled() ) {
|
||||
$pluginData = apply_filters( 'postman_get_plugin_metadata', null );
|
||||
$headers['X-Mailer'] = sprintf( 'Postman SMTP %s for WordPress (%s)', $pluginData ['version'], 'https://wordpress.org/plugins/post-smtp/' );
|
||||
}
|
||||
|
||||
foreach ( ( array ) $message->getHeaders() as $header ) {
|
||||
$this->logger->debug( sprintf( 'Adding user header %s=%s', $header ['name'], $header ['content'] ) );
|
||||
$headers[$header['name']] = $header ['content'];
|
||||
}
|
||||
|
||||
// add the messageId
|
||||
$messageId = $message->getMessageId();
|
||||
if ( ! empty( $messageId ) ) {
|
||||
$headers['message-id'] = $messageId;
|
||||
}
|
||||
|
||||
$sendSmtpEmail['headers'] = $headers;
|
||||
|
||||
// if the caller set a Content-Type header, use it
|
||||
$contentType = $message->getContentType();
|
||||
if ( ! empty( $contentType ) ) {
|
||||
$this->logger->debug( 'Some header keys are reserved. You may not include any of the following reserved headers: x-sg-id, x-sg-eid, received, dkim-signature, Content-Type, Content-Transfer-Encoding, To, From, Subject, Reply-To, CC, BCC.' );
|
||||
}
|
||||
|
||||
$cc = array();
|
||||
$duplicates = array();
|
||||
foreach ( ( array ) $message->getCcRecipients() as $recipient ) {
|
||||
|
||||
if ( ! in_array( $recipient->getEmail(), $duplicates ) ) {
|
||||
|
||||
$recipient->log($this->logger, 'Cc');
|
||||
$cc[] = array(
|
||||
'email' => $recipient->getEmail()
|
||||
);
|
||||
|
||||
if( !empty( $recipient->getName() ) ) {
|
||||
$cc['name'] = $recipient->getName();
|
||||
}
|
||||
|
||||
$duplicates[] = $recipient->getEmail();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
if( !empty( $cc ) )
|
||||
$sendSmtpEmail['cc'] = $cc;
|
||||
|
||||
$bcc = array();
|
||||
$duplicates = array();
|
||||
foreach ( ( array ) $message->getBccRecipients() as $recipient ) {
|
||||
|
||||
if ( ! in_array( $recipient->getEmail(), $duplicates ) ) {
|
||||
|
||||
$recipient->log($this->logger, 'Bcc');
|
||||
$bcc[] = array(
|
||||
'email' => $recipient->getEmail()
|
||||
);
|
||||
|
||||
if( !empty( $recipient->getName() ) ) {
|
||||
$bcc['name'] = $recipient->getName();
|
||||
}
|
||||
|
||||
$duplicates[] = $recipient->getEmail();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if( !empty( $bcc ) )
|
||||
$sendSmtpEmail['bcc'] = $bcc;
|
||||
|
||||
// add attachments
|
||||
$this->logger->debug( 'Adding attachments' );
|
||||
|
||||
$attachments = $this->addAttachmentsToMail( $message );
|
||||
|
||||
$email_attachments = array();
|
||||
|
||||
if( !empty( $attachments ) ) {
|
||||
|
||||
foreach ( $attachments as $index => $attachment ) {
|
||||
|
||||
$email_attachments[] = array(
|
||||
'name' => $attachment['file_name'],
|
||||
'content' => $attachment['content']
|
||||
);
|
||||
}
|
||||
|
||||
$sendSmtpEmail['attachment'] = $email_attachments;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
try {
|
||||
|
||||
// send the message
|
||||
if ( $this->logger->isDebug() ) {
|
||||
$this->logger->debug( 'Sending mail' );
|
||||
}
|
||||
|
||||
$response = $sendinblue->send( $sendSmtpEmail );
|
||||
|
||||
$this->transcript = print_r( $response, true );
|
||||
$this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
|
||||
$this->transcript .= print_r( $sendSmtpEmail, true );
|
||||
$this->logger->debug( 'Transcript=' . $this->transcript );
|
||||
|
||||
} catch (Exception $e) {
|
||||
|
||||
$this->transcript = $e->getMessage();
|
||||
$this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
|
||||
$this->transcript .= print_r( $sendSmtpEmail, true );
|
||||
$this->logger->debug( 'Transcript=' . $this->transcript );
|
||||
|
||||
throw $e;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.1
|
||||
* @version 1.0
|
||||
*/
|
||||
private function errorCodesMap( $error_code ) {
|
||||
switch ( $error_code ) {
|
||||
case 400:
|
||||
$message = sprintf( __( 'ERROR: Request is invalid. Check the error code in JSON. Status code is %1$s', 'post-smtp' ), $error_code );
|
||||
break;
|
||||
case 401:
|
||||
$message = sprintf( __( 'ERROR: You have not been authenticated. Make sure the provided api-key is correct. Status code is %1$s', 'post-smtp' ), $error_code );
|
||||
break;
|
||||
case 402:
|
||||
$message = sprintf( __( 'ERROR: Make sure you\'re account is activated and that you\'ve sufficient credits. Status code is %1$s', 'post-smtp' ), $error_code );
|
||||
break;
|
||||
case 403:
|
||||
$message = sprintf( __( 'ERROR: You do not have the rights to access the resource. Status code is %1$s', 'post-smtp' ), $error_code );
|
||||
break;
|
||||
case 404:
|
||||
$message = sprintf( __( 'ERROR: Make sure your calling an existing endpoint and that the parameters (object id etc.) in the path are correct. Status code is %1$s', 'post-smtp' ), $error_code );
|
||||
break;
|
||||
case 405:
|
||||
$message = sprintf( __( 'ERROR: The verb you\'re using is not allowed for this endpoint. Make sure you\'re using the correct method (GET, POST, PUT, DELETE). Status code is %1$s', 'post-smtp' ), $error_code );
|
||||
break;
|
||||
case 406:
|
||||
$message = sprintf( __( 'ERROR: The value of contentType for PUT or POST request in request headers is not application/json. Make sure the value is application/json only and not empty. Status code is %1$s', 'post-smtp' ), $error_code );
|
||||
break;
|
||||
case 429:
|
||||
$message = sprintf( __( 'ERROR: The expected rate limit is exceeded. Status code is %1$s', 'post-smtp' ), $error_code );
|
||||
break;
|
||||
default:
|
||||
$message = sprintf( __( 'ERROR: Status code is %1$s', 'post-smtp' ), $error_code );
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
}
|
||||
endif;
|
||||
@@ -0,0 +1,321 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once 'PostmanModuleTransport.php';
|
||||
|
||||
/**
|
||||
* Postman Sendinblue
|
||||
* @since 2.1
|
||||
* @version 1.0
|
||||
*/
|
||||
if( !class_exists( 'PostmanSendinblueTransport' ) ):
|
||||
class PostmanSendinblueTransport extends PostmanAbstractModuleTransport implements PostmanModuleTransport {
|
||||
|
||||
const SLUG = 'sendinblue_api';
|
||||
const PORT = 587;
|
||||
const HOST = 'smtp-relay.brevo.com';
|
||||
const PRIORITY = 50000;
|
||||
const SENDINBLUE_AUTH_OPTIONS = 'postman_sendinblue_auth_options';
|
||||
const SENDINBLUE_AUTH_SECTION = 'postman_sendinblue_auth_section';
|
||||
|
||||
/**
|
||||
* PostmanSendinblueTransport constructor.
|
||||
* @param $rootPluginFilenameAndPath
|
||||
* @since 2.1
|
||||
* @version 1.0
|
||||
*/
|
||||
public function __construct( $rootPluginFilenameAndPath ) {
|
||||
|
||||
parent::__construct ( $rootPluginFilenameAndPath );
|
||||
|
||||
// add a hook on the plugins_loaded event
|
||||
add_action ( 'admin_init', array ( $this, 'on_admin_init' ) );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
* @since 2.1
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getPort() {
|
||||
return self::PORT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @since 2.1
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getSlug() {
|
||||
return self::SLUG;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @since 2.1
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getProtocol() {
|
||||
return 'https';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @since 2.1
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getHostname() {
|
||||
return self::HOST;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.1
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getConfigurationBid( PostmanWizardSocket $hostData, $userAuthOverride, $originalSmtpServer ) {
|
||||
|
||||
$recommendation = array();
|
||||
$recommendation ['priority'] = 0;
|
||||
$recommendation ['transport'] = self::SLUG;
|
||||
$recommendation ['hostname'] = null; // scribe looks this
|
||||
$recommendation ['label'] = $this->getName();
|
||||
$recommendation['logo_url'] = $this->getLogoURL();
|
||||
|
||||
if ($hostData->hostname == self::HOST && $hostData->port == self::PORT) {
|
||||
$recommendation ['priority'] = self::PRIORITY;
|
||||
/* translators: where variables are (1) transport name (2) host and (3) port */
|
||||
$recommendation ['message'] = sprintf ( __ ( ('Postman recommends the %1$s to host %2$s on port %3$d.') ), $this->getName(), self::HOST, self::PORT );
|
||||
}
|
||||
|
||||
return $recommendation;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.1
|
||||
* @version 1.0
|
||||
*/
|
||||
public function createMailEngine() {
|
||||
|
||||
$api_key = $this->options->getSendinblueApiKey();
|
||||
require_once 'PostmanSendinblueMailEngine.php';
|
||||
$engine = new PostmanSendinblueMailEngine( $api_key );
|
||||
|
||||
return $engine;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.1
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getName() {
|
||||
|
||||
return __( 'Brevo', 'post-smtp' );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.1
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getDeliveryDetails() {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PostmanWizardSocket $socket
|
||||
* @param $winningRecommendation
|
||||
* @param $userSocketOverride
|
||||
* @param $userAuthOverride
|
||||
* @return array
|
||||
* @since 2.1
|
||||
* @version 1.0
|
||||
*/
|
||||
public function createOverrideMenu( PostmanWizardSocket $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride ) {
|
||||
|
||||
$overrideItem = parent::createOverrideMenu ( $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride );
|
||||
|
||||
// push the authentication options into the $overrideItem structure
|
||||
$overrideItem ['auth_items'] = array (
|
||||
array (
|
||||
'selected' => true,
|
||||
'name' => __ ( 'API Key', 'post-smtp' ),
|
||||
'value' => 'api_key'
|
||||
)
|
||||
);
|
||||
|
||||
return $overrideItem;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.1
|
||||
* @version 1.0
|
||||
*/
|
||||
public function on_admin_init() {
|
||||
|
||||
if( PostmanUtils::isAdmin() ) {
|
||||
|
||||
$this->addSettings();
|
||||
$this->registerStylesAndScripts();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.1
|
||||
* @version 1.0
|
||||
*/
|
||||
public function addSettings()
|
||||
{
|
||||
|
||||
add_settings_section(
|
||||
self::SENDINBLUE_AUTH_SECTION,
|
||||
__('Authentication', 'post-smtp'),
|
||||
array( $this, 'printSendinblueAuthSectionInfo' ),
|
||||
self::SENDINBLUE_AUTH_OPTIONS
|
||||
);
|
||||
|
||||
add_settings_field(
|
||||
PostmanOptions::SENDINBLUE_API_KEY,
|
||||
__( 'API Key', 'post-smtp' ),
|
||||
array( $this, 'sendinblue_api_key_callback' ),
|
||||
self::SENDINBLUE_AUTH_OPTIONS,
|
||||
self::SENDINBLUE_AUTH_SECTION
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.1
|
||||
* @version 1.0
|
||||
*/
|
||||
public function printSendinblueAuthSectionInfo() {
|
||||
|
||||
printf (
|
||||
'<p id="wizard_sendinblue_auth_help">%s</p>', sprintf ( __ ( 'Create an account at <a href="%1$s" target="_blank">%2$s (formely Sendinblue)</a> and enter <a href="%3$s" target="_blank">an API key</a> below.', 'post-smtp' ),
|
||||
'https://www.brevo.com/', 'brevo.com', 'https://account.brevo.com/advanced/api' )
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.1
|
||||
* @version 1.0
|
||||
*/
|
||||
public function sendinblue_api_key_callback() {
|
||||
|
||||
printf ( '<input type="password" autocomplete="off" id="sendinblue_api_key" name="postman_options[sendinblue_api_key]" value="%s" size="60" class="required ps-input ps-w-75" placeholder="%s"/>', null !== $this->options->getSendinblueApiKey() ? esc_attr ( PostmanUtils::obfuscatePassword ( $this->options->getSendinblueApiKey() ) ) : '', __ ( 'Required', 'post-smtp' ) );
|
||||
print ' <input type="button" id="toggleSendinblueApiKey" value="Show Password" class="button button-secondary" style="visibility:hidden" />';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.1
|
||||
* @version 1.0
|
||||
*/
|
||||
public function registerStylesAndScripts() {
|
||||
|
||||
$pluginData = apply_filters( 'postman_get_plugin_metadata', null );
|
||||
|
||||
wp_register_script (
|
||||
'postman-sendinblue',
|
||||
plugins_url ( 'Postman/Postman-Mail/postman-sendinblue.js', $this->rootPluginFilenameAndPath ),
|
||||
array (
|
||||
PostmanViewController::JQUERY_SCRIPT,
|
||||
'jquery_validation',
|
||||
PostmanViewController::POSTMAN_SCRIPT
|
||||
),
|
||||
$pluginData['version']
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.1
|
||||
* @version 1.0
|
||||
*/
|
||||
public function enqueueScript() {
|
||||
|
||||
wp_enqueue_script( 'postman-sendinblue' );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.1
|
||||
* @version 1.0
|
||||
*/
|
||||
public function printWizardAuthenticationStep() {
|
||||
print '<section class="wizard_sendinblue">';
|
||||
$this->printSendinblueAuthSectionInfo();
|
||||
printf ( '<label for="api_key">%s</label>', __ ( 'API Key', 'post-smtp' ) );
|
||||
print '<br />';
|
||||
print $this->sendinblue_api_key_callback();
|
||||
print '</section>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Socket's logo
|
||||
*
|
||||
* @since 2.1
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getLogoURL() {
|
||||
|
||||
return POST_SMTP_ASSETS . "images/logos/sendinblue.png";
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true, to prevent from errors because it's default Module Transport.
|
||||
*
|
||||
* @since 2.1.8
|
||||
* @version 1.0
|
||||
*/
|
||||
public function has_granted() {
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanTransport::getMisconfigurationMessage()
|
||||
* @since 2.1.8
|
||||
* @version 1.0
|
||||
*/
|
||||
protected function validateTransportConfiguration() {
|
||||
$messages = parent::validateTransportConfiguration ();
|
||||
$apiKey = $this->options->getSendinblueApiKey ();
|
||||
if (empty ( $apiKey )) {
|
||||
array_push ( $messages, __ ( 'API Key can not be empty', 'post-smtp' ) . '.' );
|
||||
$this->setNotConfiguredAndReady ();
|
||||
}
|
||||
if (! $this->isSenderConfigured ()) {
|
||||
array_push ( $messages, __ ( 'Message From Address can not be empty', 'post-smtp' ) . '.' );
|
||||
$this->setNotConfiguredAndReady ();
|
||||
}
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mixed $data
|
||||
* @since 2.1.8
|
||||
* @version 1.0
|
||||
*/
|
||||
public function prepareOptionsForExport($data) {
|
||||
$data = parent::prepareOptionsForExport ( $data );
|
||||
$data [PostmanOptions::SENDINBLUE_API_KEY] = PostmanOptions::getInstance ()->getSendinblueApiKey ();
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
endif;
|
||||
@@ -0,0 +1,283 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! class_exists( "PostmanSendpulseMailEngine" ) ) :
|
||||
|
||||
require 'Services/SendPulse/Handler.php';
|
||||
class PostmanSendpulseMailEngine implements PostmanMailEngine {
|
||||
|
||||
|
||||
protected $logger;
|
||||
|
||||
private $transcript;
|
||||
|
||||
private $api_key;
|
||||
|
||||
private $secret_key;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Constructor PostmanSendpulseMailEngine
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function __construct( $api_key, $secret_key ) {
|
||||
|
||||
$this->api_key = $api_key;
|
||||
|
||||
$this->secret_key = $secret_key;
|
||||
|
||||
// create the logger.
|
||||
$this->logger = new PostmanLogger( get_class( $this ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Transcript
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getTranscript()
|
||||
{
|
||||
return $this->transcript;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add attachment to the mail
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
private function addAttachmentsToMail( PostmanMessage $message ) {
|
||||
|
||||
$attachments = $message->getAttachments();
|
||||
if ( ! is_array( $attachments ) ) {
|
||||
// WordPress may a single filename or a newline-delimited string list of multiple filenames.
|
||||
$attArray = explode( PHP_EOL, $attachments );
|
||||
} else {
|
||||
$attArray = $attachments;
|
||||
}
|
||||
// otherwise WordPress sends an array.
|
||||
$attachments = array();
|
||||
foreach ( $attArray as $file ) {
|
||||
if ( ! empty( $file ) ) {
|
||||
$this->logger->debug( 'Adding attachment: ' . $file );
|
||||
|
||||
$file_name = basename( $file );
|
||||
$file_parts = explode( '.', $file_name );
|
||||
$file_type = wp_check_filetype( $file );
|
||||
$attachments[] = array(
|
||||
'content' => base64_encode( file_get_contents( $file ) ),
|
||||
'type' => $file_type['type'],
|
||||
'file_name' => $file_name,
|
||||
'disposition' => 'attachment',
|
||||
'id' => $file_parts[0],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $attachments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Structure Email to Send
|
||||
*
|
||||
* @param mixed $message class object.
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function send( PostmanMessage $message ) {
|
||||
|
||||
$options = PostmanOptions::getInstance();
|
||||
// Sendpulse preparation.
|
||||
if ( $this->logger->isDebug() ) {
|
||||
|
||||
$this->logger->debug( 'Creating SendGrid service with apiKey=' . $this->apiKey );
|
||||
}
|
||||
|
||||
$sendpulse = new PostmanSendpulse( $this->api_key, $this->secret_key );
|
||||
$sender = $message->getFromAddress();
|
||||
$senderEmail = ! empty( $sender->getEmail() ) ? $sender->getEmail() : $options->getMessageSenderEmail();
|
||||
$senderName = ! empty( $sender->getName() ) ? $sender->getName() : $options->getMessageSenderName();
|
||||
$headers = array();
|
||||
|
||||
$sender->log($this->logger, 'From');
|
||||
|
||||
$sendSmtpEmail['from'] = array(
|
||||
'name' => $senderName,
|
||||
'email' => $senderEmail
|
||||
);
|
||||
|
||||
$tos = array();
|
||||
$duplicates = array();
|
||||
|
||||
// add the to recipients.
|
||||
foreach ( (array) $message->getToRecipients() as $key => $recipient ) {
|
||||
|
||||
if ( ! array_key_exists( $recipient->getEmail(), $duplicates ) ) {
|
||||
|
||||
$tos[] = array(
|
||||
'email' => $recipient->getEmail()
|
||||
);
|
||||
|
||||
if ( ! empty( $recipient->getName() ) ) {
|
||||
|
||||
$tos[$key]['name'] = $recipient->getName();
|
||||
}
|
||||
|
||||
$duplicates[] = $recipient->getEmail();
|
||||
}
|
||||
}
|
||||
$sendSmtpEmail['to'] = $tos;
|
||||
|
||||
$sendSmtpEmail['subject'] = $message->getSubject();
|
||||
|
||||
$textPart = $message->getBodyTextPart();
|
||||
if ( ! empty( $textPart ) ) {
|
||||
$this->logger->debug( 'Adding body as text' );
|
||||
$sendSmtpEmail['text'] = $textPart;
|
||||
}
|
||||
|
||||
$htmlPart = $message->getBodyHtmlPart();
|
||||
if ( ! empty( $htmlPart ) ) {
|
||||
$this->logger->debug( 'Adding body as html' );
|
||||
$htmlPart = base64_encode( $htmlPart );
|
||||
$sendSmtpEmail['html'] = $htmlPart;
|
||||
}
|
||||
|
||||
// add the reply-to.
|
||||
$replyTo = $message->getReplyTo();
|
||||
$replies = array();
|
||||
// $replyTo is null or a PostmanEmailAddress object
|
||||
if ( isset( $replyTo ) && ! empty( $replyTo->getName() ) ) {
|
||||
$replies['to'] = array(
|
||||
'email' => $replyTo->getEmail(),
|
||||
'name' => $replyTo->getName(),
|
||||
);
|
||||
|
||||
if ( isset( $replyTo ) ) {
|
||||
$replies['to'] = array(
|
||||
'email' => $replyTo->getEmail(),
|
||||
);
|
||||
}
|
||||
$sendSmtpEmail['to'] = $replies;
|
||||
}
|
||||
|
||||
// add the Postman signature - append it to whatever the user may have set.
|
||||
if ( ! $options->isStealthModeEnabled() ) {
|
||||
$pluginData = apply_filters( 'postman_get_plugin_metadata', null );
|
||||
$headers['X-Mailer'] = sprintf( 'Postman SMTP %s for WordPress (%s)', $pluginData['version'], 'https://wordpress.org/plugins/post-smtp/' );
|
||||
}
|
||||
|
||||
foreach ( (array) $message->getHeaders() as $header ) {
|
||||
$this->logger->debug( sprintf( 'Adding user header %s=%s', $header['name'], $header['content'] ) );
|
||||
$headers[ $header['name'] ] = $header['content'];
|
||||
}
|
||||
|
||||
// add the messageId.
|
||||
$messageId = $message->getMessageId();
|
||||
if ( ! empty( $messageId ) ) {
|
||||
$headers['message-id'] = $messageId;
|
||||
}
|
||||
|
||||
$sendSmtpEmail['headers'] = $headers;
|
||||
|
||||
// if the caller set a Content-Type header, use it.
|
||||
$contentType = $message->getContentType();
|
||||
if ( ! empty( $contentType ) ) {
|
||||
$this->logger->debug('Some header keys are reserved. You may not include any of the following reserved headers: x-sg-id, x-sg-eid, received, dkim-signature, Content-Type, Content-Transfer-Encoding, To, From, Subject, Reply-To, CC, BCC.');
|
||||
}
|
||||
|
||||
$cc = array();
|
||||
$duplicates = array();
|
||||
foreach ( (array) $message->getCcRecipients() as $recipient ) {
|
||||
|
||||
if ( ! in_array( $recipient->getEmail(), $duplicates ) ) {
|
||||
|
||||
$recipient->log( $this->logger, 'Cc' );
|
||||
$cc[] = array(
|
||||
'email' => $recipient->getEmail(),
|
||||
);
|
||||
|
||||
if ( ! empty( $recipient->getName() ) ) {
|
||||
$cc['name'] = $recipient->getName();
|
||||
}
|
||||
|
||||
$duplicates[] = $recipient->getEmail();
|
||||
}
|
||||
}
|
||||
if ( ! empty( $cc ) )
|
||||
$sendSmtpEmail['cc'] = $cc;
|
||||
|
||||
$bcc = array();
|
||||
$duplicates = array();
|
||||
foreach ( (array) $message->getBccRecipients() as $recipient ) {
|
||||
|
||||
if ( ! in_array( $recipient->getEmail(), $duplicates ) ) {
|
||||
|
||||
$recipient->log( $this->logger, 'Bcc' );
|
||||
$bcc[] = array(
|
||||
'email' => $recipient->getEmail()
|
||||
);
|
||||
|
||||
if (!empty($recipient->getName())) {
|
||||
$bcc['name'] = $recipient->getName();
|
||||
}
|
||||
|
||||
$duplicates[] = $recipient->getEmail();
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $bcc ) )
|
||||
$sendSmtpEmail['bcc'] = $bcc;
|
||||
|
||||
// add attachments.
|
||||
$this->logger->debug( 'Adding attachments' );
|
||||
$attachments_array = array();
|
||||
|
||||
$attachments = $this->addAttachmentsToMail( $message );
|
||||
|
||||
if ( ! empty( $attachments ) ) {
|
||||
$attachments_array = [];
|
||||
|
||||
foreach ( $attachments as $attachment ) {
|
||||
$attachments_array[ $attachment['file_name'] ] = $attachment['content'];
|
||||
}
|
||||
|
||||
$sendSmtpEmail['attachments_binary'] = $attachments_array;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
// send the message.
|
||||
if ( $this->logger->isDebug() ) {
|
||||
$this->logger->debug( 'Sending mail' );
|
||||
}
|
||||
$final_message = array(
|
||||
|
||||
'email' => $sendSmtpEmail,
|
||||
);
|
||||
|
||||
$response = $sendpulse->send( $final_message );
|
||||
|
||||
$this->transcript = print_r( $response, true );
|
||||
$this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
|
||||
$this->transcript .= print_r( $sendSmtpEmail, true );
|
||||
$this->logger->debug( 'Transcript=' . $this->transcript );
|
||||
} catch ( Exception $e ) {
|
||||
|
||||
$this->transcript = $e->getMessage();
|
||||
$this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
|
||||
$this->transcript .= print_r( $sendSmtpEmail, true );
|
||||
$this->logger->debug( 'Transcript=' . $this->transcript );
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
endif;
|
||||
@@ -0,0 +1,364 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once 'PostmanModuleTransport.php';
|
||||
|
||||
/**
|
||||
* Postman Sendpulse
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
if ( ! class_exists( 'PostmanSendpulseTransport' ) ) :
|
||||
class PostmanSendpulseTransport extends PostmanAbstractModuleTransport implements PostmanModuleTransport {
|
||||
|
||||
const SLUG = 'sendpulse_api';
|
||||
const PORT = 2525;
|
||||
const HOST = 'smtp-pulse.com';
|
||||
const PRIORITY = 52000;
|
||||
const SENDPULSE_AUTH_OPTIONS = 'postman_sendpulse_auth_options';
|
||||
const SENDPULSE_AUTH_SECTION = 'postman_sendpulse_auth_section';
|
||||
|
||||
/**
|
||||
* PostmanSendpulseTransport constructor.
|
||||
*
|
||||
* @param $rootPluginFilenameAndPath
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function __construct( $rootPluginFilenameAndPath ) {
|
||||
|
||||
parent::__construct( $rootPluginFilenameAndPath );
|
||||
|
||||
// add a hook on the plugins_loaded event.
|
||||
add_action( 'admin_init', array( $this, 'on_admin_init' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return int
|
||||
* @since 2.7
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getPort() {
|
||||
return self::PORT;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return string
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getSlug() {
|
||||
return self::SLUG;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return string
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getProtocol() {
|
||||
return 'https';
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return string
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getHostname() {
|
||||
return self::HOST;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getConfigurationBid( PostmanWizardSocket $hostData, $userAuthOverride, $originalSmtpServer ) {
|
||||
|
||||
$recommendation = array();
|
||||
$recommendation['priority'] = 0;
|
||||
$recommendation['transport'] = self::SLUG;
|
||||
$recommendation['hostname'] = null; // scribe looks this.
|
||||
$recommendation['label'] = $this->getName();
|
||||
$recommendation['logo_url'] = $this->getLogoURL();
|
||||
|
||||
if ( $hostData->hostname == self::HOST && $hostData->port == self::PORT ) {
|
||||
$recommendation['priority'] = self::PRIORITY;
|
||||
/* translators: where variables are (1) transport name (2) host and (3) port */
|
||||
$recommendation['message'] = sprintf( __( ( 'Postman recommends the %1$s to host %2$s on port %3$d.' ) ), $this->getName(), self::HOST, self::PORT );
|
||||
}
|
||||
|
||||
return $recommendation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creating Mail Engine
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function createMailEngine() {
|
||||
|
||||
$api_key = $this->options->getSendpulseApiKey();
|
||||
$secret_key = $this->options->getSendpulseSecretKey();
|
||||
require_once 'PostmanSendpulseMailEngine.php';
|
||||
$engine = new PostmanSendpulseMailEngine( $api_key, $secret_key );
|
||||
|
||||
return $engine;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getName() {
|
||||
|
||||
return __( 'SendPulse', 'post-smtp' );
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getDeliveryDetails() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PostmanWizardSocket $socket
|
||||
* @param $winningRecommendation
|
||||
* @param $userSocketOverride
|
||||
* @param $userAuthOverride
|
||||
* @return array
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function createOverrideMenu( PostmanWizardSocket $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride ) {
|
||||
|
||||
$overrideItem = parent::createOverrideMenu( $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride );
|
||||
|
||||
// push the authentication options into the $overrideItem structure.
|
||||
$overrideItem['auth_items'] = array(
|
||||
array(
|
||||
'selected' => true,
|
||||
'name' => __( 'API Key', 'post-smtp' ),
|
||||
'value' => 'api_key'
|
||||
)
|
||||
);
|
||||
|
||||
return $overrideItem;
|
||||
}
|
||||
|
||||
/**
|
||||
* Action Hook
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function on_admin_init() {
|
||||
|
||||
if ( PostmanUtils::isAdmin() ) {
|
||||
|
||||
$this->addSettings();
|
||||
$this->registerStylesAndScripts();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Settings
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function addSettings() {
|
||||
|
||||
add_settings_section(
|
||||
self::SENDPULSE_AUTH_SECTION,
|
||||
__( 'Authentication', 'post-smtp' ),
|
||||
array( $this, 'printSendpulseAuthSectionInfo' ),
|
||||
self::SENDPULSE_AUTH_OPTIONS
|
||||
);
|
||||
|
||||
add_settings_field(
|
||||
PostmanOptions::SENDPULSE_API_KEY,
|
||||
__( 'API Key', 'post-smtp' ),
|
||||
array( $this, 'sendpulse_api_key_callback' ),
|
||||
self::SENDPULSE_AUTH_OPTIONS,
|
||||
self::SENDPULSE_AUTH_SECTION
|
||||
);
|
||||
|
||||
add_settings_field(
|
||||
PostmanOptions::SENDPULSE_SECRET_KEY,
|
||||
__( 'Secret Key', 'post-smtp' ),
|
||||
array( $this, 'sendpulse_secret_key_callback' ),
|
||||
self::SENDPULSE_AUTH_OPTIONS,
|
||||
self::SENDPULSE_AUTH_SECTION
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print Auth Section
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function printSendpulseAuthSectionInfo()
|
||||
{
|
||||
|
||||
printf(
|
||||
'<p id="wizard_sendpulse_auth_help">%s</p>',
|
||||
sprintf(
|
||||
__( 'Create an account at <a href="%1$s" target="_blank">%2$s</a> and enter <a href="%3$s" target="_blank">an API key and Secret</a> below.', 'post-smtp' ),
|
||||
'https://sendpulse.com/',
|
||||
'sendpulse.com',
|
||||
'https://login.sendpulse.com/settings/#api'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* API Callback
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function sendpulse_api_key_callback() {
|
||||
|
||||
printf( '<input type="password" autocomplete="off" id="sendpulse_api_key" name="postman_options[sendpulse_api_key]" value="%s" size="60" class="required ps-input ps-w-75" placeholder="%s"/>', null !== $this->options->getSendpulseApiKey() ? esc_attr( PostmanUtils::obfuscatePassword( $this->options->getSendpulseApiKey() ) ) : '', __( 'Required', 'post-smtp' ) );
|
||||
print ' <input type="button" id="toggleSendpulseApiKey" value="Show Password" class="button button-secondary" style="visibility:hidden" />';
|
||||
}
|
||||
|
||||
/**
|
||||
* Secret Callback
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function sendpulse_secret_key_callback() {
|
||||
|
||||
printf( '<input type="password" autocomplete="off" id="sendpulse_secret_key" name="postman_options[sendpulse_secret_key]" value="%s" size="60" class="required ps-input ps-w-75" placeholder="%s"/>', null !== $this->options->getSendpulseSecretKey() ? esc_attr( PostmanUtils::obfuscatePassword( $this->options->getSendpulseSecretKey() ) ) : '', __( 'Required', 'post-smtp' ) );
|
||||
print ' <input type="button" id="toggleSendpulseSecretKey" value="Show Password" class="button button-secondary" style="visibility:hidden" />';
|
||||
}
|
||||
|
||||
/**
|
||||
* Register Styles
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function registerStylesAndScripts() {
|
||||
|
||||
$pluginData = apply_filters( 'postman_get_plugin_metadata', null );
|
||||
|
||||
wp_register_script(
|
||||
'postman-sendpulse',
|
||||
plugins_url( 'Postman/Postman-Mail/postman-sendpulse.js', $this->rootPluginFilenameAndPath ),
|
||||
array(
|
||||
PostmanViewController::JQUERY_SCRIPT,
|
||||
'jquery_validation',
|
||||
PostmanViewController::POSTMAN_SCRIPT,
|
||||
),
|
||||
$pluginData['version']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue Script
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function enqueueScript() {
|
||||
|
||||
wp_enqueue_script( 'postman-sendpulse' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Ptint Authenitcation Section.
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function printWizardAuthenticationStep() {
|
||||
print '<section class="wizard_sendpulse">';
|
||||
$this->printSendpulseAuthSectionInfo();
|
||||
printf( '<label for="api_key">%s</label>', __( 'API ID', 'post-smtp' ) );
|
||||
print '<br />';
|
||||
print $this->sendpulse_api_key_callback();
|
||||
print '<br />';
|
||||
printf( '<label for="secret_key">%s</label>', __( 'API Secret', 'post-smtp' ) );
|
||||
print '<br />';
|
||||
print $this->sendpulse_secret_key_callback();
|
||||
print '</section>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Socket's logo
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getLogoURL() {
|
||||
|
||||
return POST_SMTP_ASSETS . 'images/logos/sendpulse.png';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true, to prevent from errors because it's default Module Transport.
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function has_granted() {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanTransport::getMisconfigurationMessage()
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
protected function validateTransportConfiguration() {
|
||||
$messages = parent::validateTransportConfiguration();
|
||||
$apiKey = $this->options->getSendpulseApiKey();
|
||||
$secretKey = $this->options->getSendpulseSecretKey();
|
||||
if ( empty( $apiKey ) ) {
|
||||
array_push( $messages, __( 'ID Key can not be empty', 'post-smtp' ) . '.' );
|
||||
$this->setNotConfiguredAndReady();
|
||||
}
|
||||
if ( empty( $secretKey ) ) {
|
||||
array_push( $messages, __( 'Secret Key can not be empty', 'post-smtp' ) . '.' );
|
||||
$this->setNotConfiguredAndReady();
|
||||
}
|
||||
if ( ! $this->isSenderConfigured() ) {
|
||||
array_push( $messages, __( 'Message From Address can not be empty', 'post-smtp' ) . '.' );
|
||||
$this->setNotConfiguredAndReady();
|
||||
}
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare Options for Export
|
||||
*
|
||||
* @param mixed $data // data.
|
||||
* @since 2.7
|
||||
* @version 1.0
|
||||
*/
|
||||
public function prepareOptionsForExport( $data ) {
|
||||
$data = parent::prepareOptionsForExport( $data );
|
||||
$data[ PostmanOptions::SENDPULSE_API_KEY ] = PostmanOptions::getInstance()->getSendpulseApiKey();
|
||||
$data[ PostmanOptions::SENDPULSE_SECRET_KEY ] = PostmanOptions::getInstance()->getSendpulseSecretKey();
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
endif;
|
||||
@@ -0,0 +1,196 @@
|
||||
<?php
|
||||
/**
|
||||
* PostmanSmtp2GoEngine
|
||||
*
|
||||
* @package Postman
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
if ( ! class_exists( 'PostmanSmtp2GoEngine' ) ) {
|
||||
|
||||
require_once 'Services/Smtp2Go/Handler.php';
|
||||
|
||||
class PostmanSmtp2GoEngine implements PostmanMailEngine {
|
||||
protected $logger;
|
||||
protected $transcript;
|
||||
protected $apiKey;
|
||||
|
||||
public function __construct( $apiKey ) {
|
||||
assert( ! empty( $apiKey ) );
|
||||
$this->apiKey = $apiKey;
|
||||
|
||||
$this->logger = new PostmanLogger( get_class( $this ) );
|
||||
}
|
||||
|
||||
public function send( $message ) {
|
||||
$options = PostmanOptions::getInstance();
|
||||
$smtp2go = new PostmanSmtp2GoHandler( $this->apiKey );
|
||||
$content = array();
|
||||
$headers = array();
|
||||
$customHeaders = array();
|
||||
|
||||
$sender = $message->getFromAddress();
|
||||
$replyTo = $message->getReplyTo();
|
||||
$senderEmail = ! empty( $sender->getEmail() ) ? $sender->getEmail() : $options->getMessageSenderEmail();
|
||||
$senderName = ! empty( $sender->getName() ) ? $sender->getName() : $options->getMessageSenderName();
|
||||
|
||||
$content['sender'] = $senderName . '<' . $senderEmail . '>';
|
||||
|
||||
$sender->log( $this->logger, 'From' );
|
||||
|
||||
$duplicates = array();
|
||||
|
||||
foreach ( (array) $message->getToRecipients() as $recipient ) {
|
||||
if ( ! in_array( $recipient->getEmail(), $duplicates ) ) {
|
||||
$name = $recipient->getName();
|
||||
$email = $recipient->getEmail();
|
||||
$content['to'][] = $name . '<' . $email . '>';
|
||||
}
|
||||
|
||||
$duplicates[] = $recipient->getEmail();
|
||||
}
|
||||
|
||||
if ( null !== $message->getSubject() ) {
|
||||
$content['subject'] = $message->getSubject();
|
||||
}
|
||||
|
||||
$textPart = $message->getBodyTextPart();
|
||||
$htmlPart = $message->getBodyHtmlPart();
|
||||
|
||||
if ( ! empty( $textPart ) ) {
|
||||
$this->logger->debug( 'Adding body as text' );
|
||||
$content['text_body'] = $textPart;
|
||||
}
|
||||
|
||||
if ( ! empty( $htmlPart ) ) {
|
||||
$this->logger->debug( 'Adding body as html' );
|
||||
$content['html_body'] = $htmlPart;
|
||||
}
|
||||
|
||||
foreach ( (array) $message->getHeaders() as $header ) {
|
||||
$this->logger->debug(
|
||||
sprintf(
|
||||
'Adding user header %s=%s',
|
||||
$header['name'],
|
||||
$header['content']
|
||||
)
|
||||
);
|
||||
|
||||
$headers[ $header['name'] ] = $header['content'];
|
||||
}
|
||||
|
||||
foreach ( (array) $message->getCcRecipients() as $recipient ) {
|
||||
if ( ! in_array( $recipient->getEmail(), $duplicates ) ) {
|
||||
$name = $recipient->getName();
|
||||
$email = $recipient->getEmail();
|
||||
$content['cc'][] = $name . '<' . $email . '>';
|
||||
}
|
||||
$duplicates[] = $recipient->getEmail();
|
||||
}
|
||||
|
||||
foreach ( (array) $message->getCcRecipients() as $recipient ) {
|
||||
if ( ! in_array( $recipient->getEmail(), $duplicates ) ) {
|
||||
$name = $recipient->getName();
|
||||
$email = $recipient->getEmail();
|
||||
$content['bcc'][] = $name . '<' . $email . '>';
|
||||
}
|
||||
$duplicates[] = $recipient->getEmail();
|
||||
}
|
||||
|
||||
if ( ! empty( $headers ) ) {
|
||||
$content['headers'] = $headers;
|
||||
}
|
||||
|
||||
if ( ! empty( $replyTo ) ) {
|
||||
// Normalize to array.
|
||||
if ( $replyTo instanceof PostmanEmailAddress ) {
|
||||
$replyTo = [ $replyTo ];
|
||||
} elseif ( ! is_array( $replyTo ) ) {
|
||||
$replyTo = [];
|
||||
}
|
||||
|
||||
foreach ( $replyTo as $reply ) {
|
||||
if ( $reply instanceof PostmanEmailAddress ) {
|
||||
$name = $reply->getName();
|
||||
$email = $reply->getEmail();
|
||||
|
||||
if ( ! empty( $email ) ) {
|
||||
$formatted = $name ? "$name <$email>" : $email;
|
||||
|
||||
$customHeaders[] = array(
|
||||
'header' => 'Reply-To',
|
||||
'value' => $formatted,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Only assign if we have valid headers.
|
||||
if ( ! empty( $customHeaders ) ) {
|
||||
$content['custom_headers'] = $customHeaders;
|
||||
}
|
||||
$this->logger->debug( 'Adding attachments' );
|
||||
|
||||
$attachments = $this->addAttachmentsToMail( $message );
|
||||
|
||||
if ( ! empty( $attachments ) ) {
|
||||
$content['attachments'] = $attachments;
|
||||
}
|
||||
|
||||
try {
|
||||
if ( $this->logger->isDebug() ) {
|
||||
$this->logger->debug( 'Sending mail' );
|
||||
}
|
||||
|
||||
$response = $smtp2go->send( $content );
|
||||
$this->transcript = print_r( $response, true );
|
||||
$this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
|
||||
$this->transcript .= print_r( $content, true );
|
||||
$this->logger->debug( 'Transcript=' . $this->transcript );
|
||||
|
||||
} catch ( Exception $e ) {
|
||||
$this->transcript = $e->getMessage();
|
||||
$this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
|
||||
$this->transcript .= print_r( $content, true );
|
||||
$this->logger->debug( 'Transcript=' . $this->transcript );
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
public function addAttachmentsToMail( $message ) {
|
||||
$attachments = $message->getAttachments();
|
||||
if ( ! is_array( $attachments ) ) {
|
||||
$attArray = explode( PHP_EOL, $attachments );
|
||||
} else {
|
||||
$attArray = $attachments;
|
||||
}
|
||||
|
||||
$attachments = array();
|
||||
|
||||
foreach ( $attArray as $file ) {
|
||||
if ( ! empty( $file ) ) {
|
||||
$this->logger->debug( 'Adding attachment: ' . $file );
|
||||
|
||||
$file_name = basename( $file );
|
||||
$file_parts = explode( '.', $file_name );
|
||||
$file_type = wp_check_filetype( $file );
|
||||
|
||||
$attachments[] = array(
|
||||
'filename' => $file_name,
|
||||
'mimetype' => $file_type['type'],
|
||||
'fileblob' => base64_encode( file_get_contents( $file ) ),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $attachments;
|
||||
}
|
||||
|
||||
public function getTranscript() {
|
||||
return $this->transcript;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
<?php
|
||||
/**
|
||||
* Extension: Smtp2Go
|
||||
* Type: Transport
|
||||
*
|
||||
* @package Postman SMTP
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
if ( ! class_exists( 'PostmanSmtp2GoTransport' ) ) {
|
||||
class PostmanSmtp2GoTransport extends PostmanAbstractModuleTransport implements PostmanModuleTransport {
|
||||
const SLUG = 'smtp2go_api';
|
||||
const PORT = 0;
|
||||
const HOST = 'api.smtp2go.com';
|
||||
const PRIORITY = 48000;
|
||||
const SMTP2GO_AUTH_OPTIONS = 'postman_smtp2go_auth_options';
|
||||
const SMTP2GO_AUTH_SECTION = 'postman_smtp2go_auth_section';
|
||||
|
||||
public function __construct( $params ) {
|
||||
parent::__construct( $params );
|
||||
|
||||
add_action( 'admin_init', array( $this, 'smtp2go_admin_init' ) );
|
||||
}
|
||||
|
||||
public function getProtocol() {
|
||||
return 'https';
|
||||
}
|
||||
|
||||
public function getSlug() {
|
||||
return self::SLUG;
|
||||
}
|
||||
|
||||
public function getName() {
|
||||
return __( 'SMTP2Go', 'post-smtp' );
|
||||
}
|
||||
|
||||
public function getHostname() {
|
||||
return self::HOST;
|
||||
}
|
||||
|
||||
public function getPort() {
|
||||
return self::PORT;
|
||||
}
|
||||
|
||||
public function getTransportType() {
|
||||
return 'Smtp2Go_api';
|
||||
}
|
||||
|
||||
public function createMailEngine() {
|
||||
$apiKey = $this->options->getSmtp2GoApiKey();
|
||||
require_once 'PostmanSmtp2GoEngine.php';
|
||||
$engine = new PostmanSmtp2GoEngine( $apiKey );
|
||||
|
||||
return $engine;
|
||||
}
|
||||
|
||||
public function getDeliveryDetails() {
|
||||
return sprintf(
|
||||
__( 'Postman will send mail via the <b>%1$s %2$s</b>.', 'post-smtp' ),
|
||||
'🔐',
|
||||
$this->getName ()
|
||||
);
|
||||
}
|
||||
|
||||
public function prepareOptionsForExport( $data ) {
|
||||
$data = parent::prepareOptionsForExport( $data );
|
||||
$data[ PostmanOptions::SMTP2GO_API_KEY ] = PostmanOptions::getInstance()->getSmtp2GoApiKey();
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected function validateTransportConfiguration() {
|
||||
$messages = parent::validateTransportConfiguration();
|
||||
$apiKey = $this->options->getSmtp2GoApiKey();
|
||||
|
||||
if ( empty( $apiKey ) ) {
|
||||
array_push( $messages, __ ( 'API Key can not be empty', 'post-smtp' ) . '.' );
|
||||
$this->setNotConfiguredAndReady();
|
||||
}
|
||||
|
||||
if ( ! $this->isSenderConfigured() ) {
|
||||
array_push ( $messages, __ ( 'Message From Address can not be empty', 'post-smtp' ) . '.' );
|
||||
$this->setNotConfiguredAndReady();
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
public function getConfigurationBid( $hostData, $userAuthOverride, $orignalSmtpServer ) {
|
||||
$recommendation = array ();
|
||||
$recommendation ['priority'] = 0;
|
||||
$recommendation ['transport'] = self::SLUG;
|
||||
$recommendation ['hostname'] = $this->getHostname(); // scribe looks this
|
||||
$recommendation ['label'] = $this->getName ();
|
||||
$recommendation['logo_url'] = $this->getLogoURL();
|
||||
|
||||
if ($hostData->hostname == self::HOST && $hostData->port == self::PORT) {
|
||||
$recommendation ['priority'] = self::PRIORITY;
|
||||
/* translators: where variables are (1) transport name (2) host and (3) port */
|
||||
$recommendation ['message'] = sprintf ( __ ( ('Postman recommends the %1$s to host %2$s on port %3$d.') ), $this->getName (), self::HOST, self::PORT );
|
||||
}
|
||||
|
||||
return $recommendation;
|
||||
}
|
||||
|
||||
public function populateConfiguration( $hostname ) {
|
||||
$response = parent::populateConfiguration( $hostname );
|
||||
return $response;
|
||||
}
|
||||
|
||||
public function createOverrideMenu( $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride ) {
|
||||
$overrideItem = parent::createOverrideMenu( $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride );
|
||||
|
||||
$overrideItem['auth_items'] = array(
|
||||
array(
|
||||
'selected' => true,
|
||||
'name' => __( 'Api Key', 'post-smtp' ),
|
||||
'value' => 'api_key'
|
||||
),
|
||||
);
|
||||
return $overrideItem;
|
||||
}
|
||||
|
||||
public function smtp2go_admin_init() {
|
||||
if ( PostmanUtils::isAdmin() ) {
|
||||
$this->addSettings();
|
||||
$this->registerStylesAndScripts();
|
||||
}
|
||||
}
|
||||
|
||||
private function addSettings() {
|
||||
add_settings_section(
|
||||
PostmanSmtp2GoTransport::SMTP2GO_AUTH_SECTION,
|
||||
__( 'Authentication', 'post-smtp' ),
|
||||
array( $this, 'printSmtp2goSectionInfo' ),
|
||||
PostmanSmtp2GoTransport::SMTP2GO_AUTH_OPTIONS
|
||||
);
|
||||
|
||||
add_settings_field(
|
||||
PostmanOptions::SMTP2GO_API_KEY,
|
||||
__( 'API Key', 'post-smtp' ),
|
||||
array( $this, 'smtp2goApiKeyCallback' ),
|
||||
PostmanSmtp2GoTransport::SMTP2GO_AUTH_OPTIONS,
|
||||
PostmanSmtp2GoTransport::SMTP2GO_AUTH_SECTION
|
||||
);
|
||||
}
|
||||
|
||||
public function printSmtp2goSectionInfo() {
|
||||
printf(
|
||||
'<p id="wizard_smtp2go_auth_help">%s</p>',
|
||||
sprintf(
|
||||
__( 'Create an account at <a href="%1$s" target="_blank">%2$s</a> and enter <a href="%3$s" target="_blank">an API key</a> below.', 'post-smtp' ),
|
||||
'https://www.smtp2go.com/',
|
||||
'smtp2go.com',
|
||||
'https://app-us.smtp2go.com/sending/apikeys/'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function smtp2goApiKeyCallback() {
|
||||
printf(
|
||||
'<input type="password" autocomplete="off" id="smtp2go_api_key" name="postman_options[smtp2go_api_key]" value="%s" size="60" class="required ps-input ps-w-75" placeholder="%s"/>',
|
||||
null !== $this->options->getSmtp2GoApiKey() ? esc_attr ( PostmanUtils::obfuscatePassword ( $this->options->getSmtp2GoApiKey () ) ) : '',
|
||||
__ ( 'Required', 'post-smtp' )
|
||||
);
|
||||
print ' <input type="button" id="toggleSmtp2goApiKey" value="Show Password" class="button button-secondary" style="visibility:hidden" />';
|
||||
}
|
||||
|
||||
private function registerStylesAndScripts() {
|
||||
$pluginData = apply_filters( 'postman_get_plugin_metadata', null );
|
||||
wp_register_script( 'postman_smtp2go_script', plugins_url( 'Postman/Postman-Mail/postman_smtp2go.js', $this->rootPluginFilenameAndPath ), array( PostmanViewController::JQUERY_SCRIPT, 'jquery_validation', PostmanViewController::POSTMAN_SCRIPT ), $pluginData['version'] );
|
||||
}
|
||||
|
||||
public function enqueueScript() {
|
||||
wp_enqueue_script( 'postman_smtp2go_script' );
|
||||
}
|
||||
|
||||
public function printWizardAuthenticationStep() {
|
||||
print '<section class="wizard_smtp2go">';
|
||||
$this->printSmtp2goSectionInfo();
|
||||
printf ( '<label for="api_key">%s</label>', __ ( 'API Key', 'post-smtp' ) );
|
||||
print '<br />';
|
||||
$this->smtp2goApiKeyCallback();
|
||||
print '</section>';
|
||||
}
|
||||
|
||||
public function getLogoURL() {
|
||||
return POST_SMTP_ASSETS . "images/logos/smtp2go.png";
|
||||
}
|
||||
|
||||
public function has_granted() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,735 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
require_once 'PostmanModuleTransport.php';
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jasonhendriks
|
||||
*/
|
||||
class PostmanSmtpModuleTransport extends PostmanAbstractZendModuleTransport implements PostmanZendModuleTransport {
|
||||
const SLUG = 'smtp';
|
||||
public function __construct( $rootPluginFilenameAndPath ) {
|
||||
parent::__construct( $rootPluginFilenameAndPath );
|
||||
|
||||
// add a hook on the plugins_loaded event
|
||||
add_action( 'admin_init', array(
|
||||
$this,
|
||||
'on_admin_init',
|
||||
) );
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanModuleTransport::createMailEngine()
|
||||
*/
|
||||
public function createMailEngine() {
|
||||
require_once 'PostmanZendMailEngine.php';
|
||||
return new PostmanZendMailEngine( $this );
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanZendModuleTransport::createZendMailTransport()
|
||||
*/
|
||||
public function createZendMailTransport( $fakeHostname, $fakeConfig ) {
|
||||
if ( PostmanOptions::AUTHENTICATION_TYPE_OAUTH2 == $this->getAuthenticationType() ) {
|
||||
$config = PostmanOAuth2ConfigurationFactory::createConfig( $this );
|
||||
} else {
|
||||
$config = PostmanBasicAuthConfigurationFactory::createConfig( $this );
|
||||
}
|
||||
return new Postman_Zend_Mail_Transport_Smtp( $this->getHostname(), $config );
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether Mail Engine locking is needed
|
||||
*
|
||||
* @see PostmanModuleTransport::requiresLocking()
|
||||
*/
|
||||
public function isLockingRequired() {
|
||||
return PostmanOptions::AUTHENTICATION_TYPE_OAUTH2 == $this->getAuthenticationType();
|
||||
}
|
||||
public function getSlug() {
|
||||
return self::SLUG;
|
||||
}
|
||||
public function getName() {
|
||||
return 'Other SMTP';
|
||||
}
|
||||
public function getHostname() {
|
||||
$this->options = $this->options;
|
||||
return $this->options->getHostname();
|
||||
}
|
||||
public function getPort() {
|
||||
$this->options = $this->options;
|
||||
return $this->options->getPort();
|
||||
}
|
||||
public function getAuthenticationType() {
|
||||
return $this->options->getAuthenticationType();
|
||||
}
|
||||
public function getCredentialsId() {
|
||||
$this->options = $this->options;
|
||||
if ( $this->options->isAuthTypeOAuth2() ) {
|
||||
return $this->options->getClientId();
|
||||
} else {
|
||||
return $this->options->getUsername();
|
||||
}
|
||||
}
|
||||
public function getCredentialsSecret() {
|
||||
$this->options = $this->options;
|
||||
if ( $this->options->isAuthTypeOAuth2() ) {
|
||||
return $this->options->getClientSecret();
|
||||
} else {
|
||||
return $this->options->getPassword();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanTransport::getMisconfigurationMessage()
|
||||
*/
|
||||
protected function validateTransportConfiguration() {
|
||||
$messages = parent::validateTransportConfiguration();
|
||||
if ( ! $this->isHostConfigured( $this->options ) ) {
|
||||
array_push( $messages, __( 'Outgoing Mail Server Hostname and Port can not be empty.', 'post-smtp' ) );
|
||||
$this->setNotConfiguredAndReady();
|
||||
}
|
||||
if ( ! $this->isEnvelopeFromConfigured() ) {
|
||||
array_push( $messages, __( 'Envelope-From Email Address can not be empty', 'post-smtp' ) . '.' );
|
||||
$this->setNotConfiguredAndReady();
|
||||
}
|
||||
if ( $this->options->isAuthTypePassword() && ! $this->isPasswordAuthenticationConfigured( $this->options ) ) {
|
||||
array_push( $messages, __( 'Username and password can not be empty.', 'post-smtp' ) );
|
||||
$this->setNotConfiguredAndReady();
|
||||
}
|
||||
if ( $this->getAuthenticationType() == PostmanOptions::AUTHENTICATION_TYPE_OAUTH2 ) {
|
||||
if ( ! $this->isOAuth2SupportedHostConfigured() ) {
|
||||
/* translators: %1$s is the Client ID label, and %2$s is the Client Secret label (e.g. Warning: OAuth 2.0 authentication requires an OAuth 2.0-capable Outgoing Mail Server, Sender Email Address, Client ID, and Client Secret.) */
|
||||
array_push( $messages, sprintf( __( 'OAuth 2.0 authentication requires a supported OAuth 2.0-capable Outgoing Mail Server.', 'post-smtp' ) ) );
|
||||
$this->setNotConfiguredAndReady();
|
||||
}
|
||||
}
|
||||
if ( empty( $messages ) ) {
|
||||
$this->setReadyForOAuthGrant();
|
||||
if ( $this->isPermissionNeeded( $this->options, $this->getOAuthToken() ) ) {
|
||||
/* translators: %1$s is the Client ID label, and %2$s is the Client Secret label */
|
||||
$message = sprintf( __( 'You have configured OAuth 2.0 authentication, but have not received permission to use it.', 'post-smtp' ), $this->getScribe()->getClientIdLabel(), $this->getScribe()->getClientSecretLabel() );
|
||||
$message .= sprintf( ' <a href="%s">%s</a>.', PostmanUtils::getGrantOAuthPermissionUrl(), $this->getScribe()->getRequestPermissionLinkText() );
|
||||
array_push( $messages, $message );
|
||||
$this->setNotConfiguredAndReady();
|
||||
}
|
||||
}
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private function isOAuth2SupportedHostConfigured() {
|
||||
$options = PostmanOptions::getInstance();
|
||||
$hostname = $options->getHostname();
|
||||
$supportedOAuthProvider = $this->isServiceProviderGoogle( $hostname ) || $this->isServiceProviderMicrosoft( $hostname ) || $this->isServiceProviderYahoo( $hostname );
|
||||
return $supportedOAuthProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a hostname, what ports should we test?
|
||||
*
|
||||
* May return an array of several combinations.
|
||||
*/
|
||||
public function getSocketsForSetupWizardToProbe( $hostname, $smtpServerGuess ) {
|
||||
$hosts = array(
|
||||
$this->createSocketDefinition( $hostname, 25 ),
|
||||
$this->createSocketDefinition( $hostname, 465 ),
|
||||
$this->createSocketDefinition( $hostname, 587 ),
|
||||
);
|
||||
|
||||
return $hosts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a single socket for the Wizard to test
|
||||
*/
|
||||
protected function createSocketDefinition( $hostname, $port ) {
|
||||
$socket = parent::createSocketDefinition( $hostname, $port );
|
||||
$socket ['smtp'] = true;
|
||||
return $socket;
|
||||
}
|
||||
|
||||
/**
|
||||
* SendGrid will never recommend it's configuration
|
||||
*
|
||||
* @param mixed $hostData
|
||||
*/
|
||||
public function getConfigurationBid( PostmanWizardSocket $hostData, $userAuthOverride, $originalSmtpServer ) {
|
||||
$port = $hostData->port;
|
||||
$hostname = $hostData->hostname;
|
||||
// because some servers, like smtp.broadband.rogers.com, report XOAUTH2 but have no OAuth2 front-end
|
||||
$supportedOAuth2Provider = $this->isServiceProviderGoogle( $hostname ) || $this->isServiceProviderMicrosoft( $hostname ) || $this->isServiceProviderYahoo( $hostname );
|
||||
$score = 1;
|
||||
$recommendation = array();
|
||||
// increment score for auth type
|
||||
if ( $hostData->mitm ) {
|
||||
$this->logger->debug( 'Losing points for MITM' );
|
||||
$score -= 10000;
|
||||
$recommendation ['mitm'] = true;
|
||||
}
|
||||
if ( ! empty( $originalSmtpServer ) && $hostname != $originalSmtpServer ) {
|
||||
$this->logger->debug( 'Losing points for Not The Original SMTP server' );
|
||||
$score -= 10000;
|
||||
}
|
||||
$secure = true;
|
||||
if ( $hostData->startTls ) {
|
||||
// STARTTLS was formalized in 2002
|
||||
// http://www.rfc-editor.org/rfc/rfc3207.txt
|
||||
$recommendation ['enc'] = PostmanOptions::SECURITY_TYPE_STARTTLS;
|
||||
$score += 30000;
|
||||
} elseif ( $hostData->protocol == 'SMTPS' ) {
|
||||
// "The hopelessly confusing and imprecise term, SSL,
|
||||
// has often been used to indicate the SMTPS wrapper and
|
||||
// TLS to indicate the STARTTLS protocol extension."
|
||||
// http://stackoverflow.com/a/19942206/4368109
|
||||
$recommendation ['enc'] = PostmanOptions::SECURITY_TYPE_SMTPS;
|
||||
$score += 28000;
|
||||
} elseif ( $hostData->protocol == 'SMTP' ) {
|
||||
$recommendation ['enc'] = PostmanOptions::SECURITY_TYPE_NONE;
|
||||
$score += 26000;
|
||||
$secure = false;
|
||||
}
|
||||
|
||||
// if there is a way to send mail....
|
||||
if ( $score > 10 ) {
|
||||
|
||||
// determine the authentication type
|
||||
if ( $hostData->auth_xoauth && $supportedOAuth2Provider && (empty( $userAuthOverride ) || $userAuthOverride == 'oauth2') ) {
|
||||
$recommendation ['auth'] = PostmanOptions::AUTHENTICATION_TYPE_OAUTH2;
|
||||
$recommendation ['display_auth'] = 'oauth2';
|
||||
$score += 500;
|
||||
if ( ! $secure ) {
|
||||
$this->logger->debug( 'Losing points for sending credentials in the clear' );
|
||||
$score -= 10000;
|
||||
}
|
||||
} elseif ( $hostData->auth_crammd5 && (empty( $userAuthOverride ) || $userAuthOverride == 'password') ) {
|
||||
$recommendation ['auth'] = PostmanOptions::AUTHENTICATION_TYPE_CRAMMD5;
|
||||
$recommendation ['display_auth'] = 'password';
|
||||
$score += 400;
|
||||
if ( ! $secure ) {
|
||||
$this->logger->debug( 'Losing points for sending credentials in the clear' );
|
||||
$score -= 10000;
|
||||
}
|
||||
} elseif ( $hostData->authPlain && (empty( $userAuthOverride ) || $userAuthOverride == 'password') ) {
|
||||
$recommendation ['auth'] = PostmanOptions::AUTHENTICATION_TYPE_PLAIN;
|
||||
$recommendation ['display_auth'] = 'password';
|
||||
$score += 300;
|
||||
if ( ! $secure ) {
|
||||
$this->logger->debug( 'Losing points for sending credentials in the clear' );
|
||||
$score -= 10000;
|
||||
}
|
||||
} elseif ( $hostData->auth_login && (empty( $userAuthOverride ) || $userAuthOverride == 'password') ) {
|
||||
$recommendation ['auth'] = PostmanOptions::AUTHENTICATION_TYPE_LOGIN;
|
||||
$recommendation ['display_auth'] = 'password';
|
||||
$score += 200;
|
||||
if ( ! $secure ) {
|
||||
$this->logger->debug( 'Losing points for sending credentials in the clear' );
|
||||
$score -= 10000;
|
||||
}
|
||||
} else if ( empty( $userAuthOverride ) || $userAuthOverride == 'none' ) {
|
||||
$recommendation ['auth'] = PostmanOptions::AUTHENTICATION_TYPE_NONE;
|
||||
$recommendation ['display_auth'] = 'none';
|
||||
$score += 100;
|
||||
}
|
||||
|
||||
// tiny weighting to prejudice the port selection, all things being equal
|
||||
if ( $port == 587 ) {
|
||||
$score += 4;
|
||||
} elseif ( $port == 25 ) {
|
||||
// "due to the prevalence of machines that have worms,
|
||||
// viruses, or other malicious software that generate large amounts of
|
||||
// spam, many sites now prohibit outbound traffic on the standard SMTP
|
||||
// port (port 25), funneling all mail submissions through submission
|
||||
// servers."
|
||||
// http://www.rfc-editor.org/rfc/rfc6409.txt
|
||||
$score += 3;
|
||||
} elseif ( $port == 465 ) {
|
||||
// use of port 465 for SMTP was deprecated in 1998
|
||||
// http://www.imc.org/ietf-apps-tls/mail-archive/msg00204.html
|
||||
$score += 2;
|
||||
} else {
|
||||
$score += 1;
|
||||
}
|
||||
|
||||
// create the recommendation message for the user
|
||||
// this can only be set if there is a valid ['auth'] and ['enc']
|
||||
$transportDescription = $this->getTransportDescription( $recommendation ['enc'] );
|
||||
$authDesc = $this->getAuthenticationDescription( $recommendation ['auth'] );
|
||||
$recommendation ['label'] = sprintf( 'SMTP - %2$s:%3$d', $transportDescription, $hostData->hostnameDomainOnly, $port );
|
||||
/* translators: where %1$s is a description of the transport (eg. SMTPS-SSL), %2$s is a description of the authentication (eg. Password-CRAMMD5), %3$d is the TCP port (eg. 465), %4$d is the hostname */
|
||||
$recommendation ['message'] = sprintf( __( 'Postman recommends %1$s with %2$s authentication to host %4$s on port %3$d.', 'post-smtp' ), $transportDescription, $authDesc, $port, $hostname );
|
||||
}
|
||||
|
||||
// fill-in the rest of the recommendation
|
||||
$recommendation ['transport'] = PostmanSmtpModuleTransport::SLUG;
|
||||
$recommendation ['priority'] = $score;
|
||||
$recommendation ['port'] = $port;
|
||||
$recommendation ['hostname'] = $hostname;
|
||||
$recommendation ['transport'] = self::SLUG;
|
||||
$recommendation['logo_url'] = $this->getLogoURL();
|
||||
|
||||
return $recommendation;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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->addSettings();
|
||||
$this->registerStylesAndScripts();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function registerStylesAndScripts() {
|
||||
// register the stylesheet and javascript external resources
|
||||
$pluginData = apply_filters( 'postman_get_plugin_metadata', null );
|
||||
wp_register_script( 'postman_smtp_script', plugins_url( 'Postman/Postman-Mail/postman_smtp.js', $this->rootPluginFilenameAndPath ), array(
|
||||
PostmanViewController::JQUERY_SCRIPT,
|
||||
'jquery_validation',
|
||||
PostmanViewController::POSTMAN_SCRIPT,
|
||||
), $pluginData ['version'] );
|
||||
}
|
||||
|
||||
/*
|
||||
* What follows in the code responsible for creating the Admin Settings page
|
||||
*/
|
||||
|
||||
/**
|
||||
*/
|
||||
public function enqueueScript() {
|
||||
wp_enqueue_script( 'postman_smtp_script' );
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function addSettings() {
|
||||
$transport = $this;
|
||||
$this->options = $this->options;
|
||||
$oauthScribe = $transport->getScribe();
|
||||
$gmail_oneclick_enabled = in_array( 'gmail-oneclick', get_option( 'post_smtp_pro', [] )['extensions'] ?? [] );
|
||||
// Sanitize
|
||||
add_settings_section( PostmanAdminController::SMTP_SECTION, __( 'Transport Settings', 'post-smtp' ), array(
|
||||
$this,
|
||||
'printSmtpSectionInfo',
|
||||
), PostmanAdminController::SMTP_OPTIONS );
|
||||
|
||||
add_settings_field( PostmanOptions::HOSTNAME, __( 'Outgoing Mail Server Hostname', 'post-smtp' ), array(
|
||||
$this,
|
||||
'hostname_callback',
|
||||
), PostmanAdminController::SMTP_OPTIONS, PostmanAdminController::SMTP_SECTION );
|
||||
|
||||
add_settings_field( PostmanOptions::PORT, __( 'Outgoing Mail Server Port', 'post-smtp' ), array(
|
||||
$this,
|
||||
'port_callback',
|
||||
), PostmanAdminController::SMTP_OPTIONS, PostmanAdminController::SMTP_SECTION );
|
||||
|
||||
add_settings_field( PostmanOptions::ENVELOPE_SENDER, __( 'Envelope-From Email Address', 'post-smtp' ), array(
|
||||
$this,
|
||||
'sender_email_callback',
|
||||
), PostmanAdminController::SMTP_OPTIONS, PostmanAdminController::SMTP_SECTION );
|
||||
|
||||
add_settings_field( PostmanOptions::SECURITY_TYPE, _x( 'Security', 'Configuration Input Field', 'post-smtp' ), array(
|
||||
$this,
|
||||
'encryption_type_callback',
|
||||
), PostmanAdminController::SMTP_OPTIONS, PostmanAdminController::SMTP_SECTION );
|
||||
|
||||
add_settings_field( PostmanOptions::AUTHENTICATION_TYPE, __( 'Authentication', 'post-smtp' ), array(
|
||||
$this,
|
||||
'authentication_type_callback',
|
||||
), PostmanAdminController::SMTP_OPTIONS, PostmanAdminController::SMTP_SECTION );
|
||||
|
||||
add_settings_section( PostmanAdminController::BASIC_AUTH_SECTION, __( 'Authentication', 'post-smtp' ), array(
|
||||
$this,
|
||||
'printBasicAuthSectionInfo',
|
||||
), PostmanAdminController::BASIC_AUTH_OPTIONS );
|
||||
|
||||
add_settings_field( PostmanOptions::BASIC_AUTH_USERNAME, __( 'Username', 'post-smtp' ), array(
|
||||
$this,
|
||||
'basic_auth_username_callback',
|
||||
), PostmanAdminController::BASIC_AUTH_OPTIONS, PostmanAdminController::BASIC_AUTH_SECTION );
|
||||
|
||||
add_settings_field( PostmanOptions::BASIC_AUTH_PASSWORD, __( 'Password', 'post-smtp' ), array(
|
||||
$this,
|
||||
'basic_auth_password_callback',
|
||||
), PostmanAdminController::BASIC_AUTH_OPTIONS, PostmanAdminController::BASIC_AUTH_SECTION );
|
||||
|
||||
// the OAuth section
|
||||
add_settings_section( PostmanAdminController::OAUTH_SECTION, __( 'Authentication', 'post-smtp' ), array(
|
||||
$this,
|
||||
'printOAuthSectionInfo',
|
||||
), PostmanAdminController::OAUTH_AUTH_OPTIONS );
|
||||
|
||||
add_settings_field(
|
||||
'enable_gmail_oneclick',
|
||||
__( 'Enable One-Click Setup '.(post_smtp_has_pro() ? '': '<span class="ps-wizard-pro-tag">PRO</span>').'', 'post-smtp' ),
|
||||
array( $this, 'renderGmailOneClickSwitch' ),
|
||||
PostmanAdminController::OAUTH_AUTH_OPTIONS,
|
||||
PostmanAdminController::OAUTH_SECTION
|
||||
);
|
||||
|
||||
add_settings_field( 'callback_domain', sprintf( '<span id="callback_domain">%s</span>', $oauthScribe->getCallbackDomainLabel() ), array(
|
||||
$this,
|
||||
'callback_domain_callback',
|
||||
), PostmanAdminController::OAUTH_AUTH_OPTIONS, PostmanAdminController::OAUTH_SECTION );
|
||||
|
||||
add_settings_field( 'redirect_url', sprintf( '<span id="redirect_url">%s</span>', $oauthScribe->getCallbackUrlLabel() ), array(
|
||||
$this,
|
||||
'redirect_url_callback',
|
||||
), PostmanAdminController::OAUTH_AUTH_OPTIONS, PostmanAdminController::OAUTH_SECTION );
|
||||
|
||||
add_settings_field( PostmanOptions::CLIENT_ID, $oauthScribe->getClientIdLabel(), array(
|
||||
$this,
|
||||
'oauth_client_id_callback',
|
||||
), PostmanAdminController::OAUTH_AUTH_OPTIONS, PostmanAdminController::OAUTH_SECTION );
|
||||
|
||||
add_settings_field( PostmanOptions::CLIENT_SECRET, $oauthScribe->getClientSecretLabel(), array(
|
||||
$this,
|
||||
'oauth_client_secret_callback',
|
||||
), PostmanAdminController::OAUTH_AUTH_OPTIONS, PostmanAdminController::OAUTH_SECTION );
|
||||
|
||||
$hide_style = $gmail_oneclick_enabled ? '' : 'style="display:none;"';
|
||||
add_settings_field(
|
||||
'gmail_auth_buttons',
|
||||
'<span class="ps-disable-gmail-setup" '. $hide_style .' >' . __( 'Gmail Authorization', 'post-smtp' ) . '</span>',
|
||||
array( $this, 'renderGmailAuthButtons' ),
|
||||
PostmanAdminController::OAUTH_AUTH_OPTIONS,
|
||||
PostmanAdminController::OAUTH_SECTION
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the Section text
|
||||
*/
|
||||
public function printSmtpSectionInfo() {
|
||||
print __( 'Configure the communication with the mail server.', 'post-smtp' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the settings option array and print one of its values
|
||||
*/
|
||||
public function hostname_callback() {
|
||||
printf( '<input type="text" id="input_hostname" name="postman_options[hostname]" value="%s" size="40" class="required" placeholder="%s"/>', null !== $this->options->getHostname() ? esc_attr( $this->options->getHostname() ) : '', __( 'Required', 'post-smtp' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the settings option array and print one of its values
|
||||
*/
|
||||
public function port_callback( $args ) {
|
||||
printf( '<input type="text" id="input_port" name="postman_options[port]" value="%s" %s placeholder="%s"/>', null !== $this->options->getPort() ? esc_attr( $this->options->getPort() ) : '', isset( $args ['style'] ) ? $args ['style'] : '', __( 'Required', 'post-smtp' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the settings option array and print one of its values
|
||||
*/
|
||||
public function encryption_type_callback() {
|
||||
$encType = $this->options->getEncryptionType();
|
||||
print '<select id="input_enc_type" class="input_encryption_type" name="postman_options[enc_type]">';
|
||||
printf( '<option class="input_enc_type_none" value="%s" %s>%s</option>', PostmanOptions::SECURITY_TYPE_NONE, $encType == PostmanOptions::SECURITY_TYPE_NONE ? 'selected="selected"' : '', __( 'None', 'post-smtp' ) );
|
||||
printf( '<option class="input_enc_type_ssl" value="%s" %s>%s</option>', PostmanOptions::SECURITY_TYPE_SMTPS, $encType == PostmanOptions::SECURITY_TYPE_SMTPS ? 'selected="selected"' : '', 'SMTPS' );
|
||||
printf( '<option class="input_enc_type_tls" value="%s" %s>%s</option>', PostmanOptions::SECURITY_TYPE_STARTTLS, $encType == PostmanOptions::SECURITY_TYPE_STARTTLS ? 'selected="selected"' : '', 'STARTTLS' );
|
||||
print '</select>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the settings option array and print one of its values
|
||||
*/
|
||||
public function authentication_type_callback() {
|
||||
$authType = $this->options->getAuthenticationType();
|
||||
printf( '<select id="input_%2$s" class="input_%2$s" name="%1$s[%2$s]">', PostmanOptions::POSTMAN_OPTIONS, PostmanOptions::AUTHENTICATION_TYPE );
|
||||
printf( '<option class="input_auth_type_none" value="%s" %s>%s</option>', PostmanOptions::AUTHENTICATION_TYPE_NONE, $authType == PostmanOptions::AUTHENTICATION_TYPE_NONE ? 'selected="selected"' : '', 'None' );
|
||||
printf( '<option class="input_auth_type_plain" value="%s" %s>%s</option>', PostmanOptions::AUTHENTICATION_TYPE_PLAIN, $authType == PostmanOptions::AUTHENTICATION_TYPE_PLAIN ? 'selected="selected"' : '', 'Plain' );
|
||||
printf( '<option class="input_auth_type_login" value="%s" %s>%s</option>', PostmanOptions::AUTHENTICATION_TYPE_LOGIN, $authType == PostmanOptions::AUTHENTICATION_TYPE_LOGIN ? 'selected="selected"' : '', 'Login' );
|
||||
printf( '<option class="input_auth_type_crammd5" value="%s" %s>%s</option>', PostmanOptions::AUTHENTICATION_TYPE_CRAMMD5, $authType == PostmanOptions::AUTHENTICATION_TYPE_CRAMMD5 ? 'selected="selected"' : '', 'CRAM-MD5' );
|
||||
printf( '<option class="input_auth_type_oauth2" value="%s" %s>%s</option>', PostmanOptions::AUTHENTICATION_TYPE_OAUTH2, $authType == PostmanOptions::AUTHENTICATION_TYPE_OAUTH2 ? 'selected="selected"' : '', 'OAuth 2.0' );
|
||||
print '</select>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the Section text
|
||||
*/
|
||||
public function printBasicAuthSectionInfo() {
|
||||
print __( 'Enter the account credentials.', 'post-smtp' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the settings option array and print one of its values
|
||||
*/
|
||||
public function basic_auth_username_callback() {
|
||||
$inputValue = (null !== $this->options->getUsername() ? esc_attr( $this->options->getUsername() ) : '');
|
||||
$inputDescription = __( 'The Username is usually the same as the Envelope-From Email Address.', 'post-smtp' );
|
||||
print ('<input tabindex="99" id="fake_user_name" name="fake_user[name]" style="position:absolute; top:-500px;" type="text" value="Safari Autofill Me">') ;
|
||||
printf( '<input type="text" id="input_basic_auth_username" name="postman_options[basic_auth_username]" value="%s" size="40" class="required ps-w-75" placeholder="%s"/><br/><span class="postman_input_description ps-input ps-w-75">%s</span>', $inputValue, __( 'Required', 'post-smtp' ), $inputDescription );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the settings option array and print one of its values
|
||||
*/
|
||||
public function basic_auth_password_callback() {
|
||||
printf(
|
||||
'<input type="password" id="input_basic_auth_password"
|
||||
name="postman_options[basic_auth_password]"
|
||||
value="%s" size="40"
|
||||
class="required ps-w-75"
|
||||
placeholder="%s"
|
||||
autocomplete="new-password"/>',
|
||||
null !== $this->options->getPassword() ? esc_attr( PostmanUtils::obfuscatePassword( $this->options->getPassword() ) ) : '',
|
||||
__( 'Required', 'post-smtp' )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the settings option array and print one of its values
|
||||
*/
|
||||
public function oauth_client_id_callback() {
|
||||
printf( '<input type="text" onClick="this.setSelectionRange(0, this.value.length)" id="oauth_client_id" name="postman_options[oauth_client_id]" value="%s" size="60" class="required ps-w-75" placeholder="%s"/>', null !== $this->options->getClientId() ? esc_attr( $this->options->getClientId() ) : '', __( 'Required', 'post-smtp' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the settings option array and print one of its values
|
||||
*/
|
||||
public function oauth_client_secret_callback() {
|
||||
printf( '<input type="text" onClick="this.setSelectionRange(0, this.value.length)" autocomplete="off" id="oauth_client_secret" name="postman_options[oauth_client_secret]" value="%s" size="60" class="required ps-w-75" placeholder="%s"/>', null !== $this->options->getClientSecret() ? esc_attr( $this->options->getClientSecret() ) : '', __( 'Required', 'post-smtp' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the Gmail One-Click Setup switch.
|
||||
*
|
||||
* Displays a toggle switch for enabling or disabling the Gmail One-Click Setup feature.
|
||||
*
|
||||
* @since 3.1.0
|
||||
*/
|
||||
public function renderGmailOneClickSwitch() {
|
||||
$url = POST_SMTP_URL . '/Postman/Wizard/assets/images/wizard-google.png';
|
||||
$data = array(
|
||||
'transport_name' => '<strong>1-Click</strong> Google Mailer Setup?',
|
||||
'product_url' => 'https://postmansmtp.com/pricing/?utm_source=plugin&utm_medium=wizard_gmail_one_click&utm_campaign=plugin',
|
||||
);
|
||||
$json_data = htmlspecialchars( json_encode( $data ), ENT_QUOTES, 'UTF-8' );
|
||||
$post_smtp_pro_options = get_option( 'post_smtp_pro', [] );
|
||||
$bonus_extensions = isset( $post_smtp_pro_options['extensions'] ) ? $post_smtp_pro_options['extensions'] : array();
|
||||
$gmail_oneclick_enabled = in_array( 'gmail-oneclick', $bonus_extensions );
|
||||
$is_checked = $gmail_oneclick_enabled ? 'checked' : '';
|
||||
$is_disabled = ! post_smtp_has_pro() ? 'disabled' : '';
|
||||
$class = 'ps-enable-gmail-one-click ' . ( ! post_smtp_has_pro() ? ' disabled' : '' );
|
||||
|
||||
// Add popup trigger file
|
||||
require_once POST_SMTP_PATH. '/Postman/Popup/popup.php';
|
||||
|
||||
echo '<div class="ps-form-switch-control">
|
||||
<label class="ps-switch-1 '.(!post_smtp_has_pro() ? 'ps-gmail-one-click' : '').'">
|
||||
<input type="hidden" id="ps-one-click-data" value="' . esc_attr( $json_data ) . '">
|
||||
<input type="checkbox" class="' . esc_attr( $class ) . '" name="enable_gmail_oneclick" ' . $is_checked .'>
|
||||
<span class="slider round"></span>
|
||||
</label>
|
||||
'.esc_html__('Enable the option for a quick and easy way to connect with Google without the need of manually creating an app.', 'post-smtp').'
|
||||
</div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Render Gmail OAuth buttons.
|
||||
*
|
||||
* Displays buttons to connect to or disconnect from Gmail using OAuth authentication.
|
||||
*
|
||||
* @since 3.1.0
|
||||
*/
|
||||
public function renderGmailAuthButtons() {
|
||||
// Action URLs for buttons.
|
||||
$nonce = wp_create_nonce( 'remove_oauth_action' );
|
||||
$postman_auth_token = get_option( 'postman_auth_token' );
|
||||
$auth_url = get_option( 'post_smtp_gmail_auth_url' );
|
||||
$post_smtp_pro_options = get_option( 'post_smtp_pro', [] );
|
||||
$bonus_extensions = isset( $post_smtp_pro_options['extensions'] ) ? $post_smtp_pro_options['extensions'] : array();
|
||||
$gmail_oneclick_enabled = in_array( 'gmail-oneclick', $bonus_extensions );
|
||||
$remove_auth_url = esc_url( add_query_arg(
|
||||
array(
|
||||
'_wpnonce' => $nonce,
|
||||
'action' => 'remove_oauth_action',
|
||||
),
|
||||
admin_url( 'admin-post.php' )
|
||||
) );
|
||||
|
||||
// Determine whether to hide the entire Gmail auth section
|
||||
$hide_style = $gmail_oneclick_enabled ? '' : 'style="display:none;"';
|
||||
|
||||
$helping_text = "<p>By signing in with Google, you can send emails using different 'From' addresses. To do this, disable the 'Force From Email' setting and use your registered aliases as the 'From' address across your WordPress site.</p> <p>Removing the OAuth connection will give you the ability to redo the OAuth connection or link to another Google account.</p>";
|
||||
|
||||
echo '<div id="ps-gmail-auth-buttons" ' . $hide_style . '>';
|
||||
|
||||
if ( ! empty( $postman_auth_token ) && isset( $postman_auth_token['user_email'] ) ) {
|
||||
// Show the "Remove Authorization" button if token exists
|
||||
echo '<a href="' . esc_url( $remove_auth_url ) . '" class="button button-secondary ps-remove-gmail-btn ps-disable-gmail-setup">';
|
||||
echo esc_html__( 'Remove Authorization', 'post-smtp' );
|
||||
echo '</a>';
|
||||
|
||||
// Show connected email
|
||||
if ( isset( $postman_auth_token['user_email'] ) ) {
|
||||
echo '<b class="ps-connect-with ps-disable-gmail-setup" style="position: relative; top: 10px;">' .
|
||||
sprintf( esc_html__( 'Connected with: %s', 'post-smtp' ), esc_html( $postman_auth_token['user_email'] ) ) .
|
||||
'</b>';
|
||||
}
|
||||
} else {
|
||||
// Show the "Sign in with Google" button
|
||||
echo '<a href="' . esc_url( $auth_url ) . '" class="button button-primary ps-gmail-btn" id="ps-wizard-connect-gmail">';
|
||||
echo esc_html__( 'Sign in with Google', 'post-smtp' );
|
||||
echo '</a>';
|
||||
echo $helping_text;
|
||||
}
|
||||
|
||||
echo '</div>';
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Print the Section text
|
||||
*/
|
||||
public function printOAuthSectionInfo() {
|
||||
$this->options = $this->options;
|
||||
$transport = $this;
|
||||
$oauthScribe = $transport->getScribe();
|
||||
printf( '<p id="wizard_oauth2_help">%s</p>', $oauthScribe->getOAuthHelp() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the settings option array and print one of its values
|
||||
*/
|
||||
public function callback_domain_callback() {
|
||||
printf( '<input type="text" onClick="this.setSelectionRange(0, this.value.length)" readonly="readonly" class="ps-input ps-w-75" id="input_oauth_callback_domain" value="%s" size="60"/>', $this->getCallbackDomain() );
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
private function getCallbackDomain() {
|
||||
try {
|
||||
$this->options = $this->options;
|
||||
$transport = $this;
|
||||
$oauthScribe = $transport->getScribe();
|
||||
return $oauthScribe->getCallbackDomain();
|
||||
} catch ( Exception $e ) {
|
||||
return __( 'Error computing your domain root - please enter it manually', 'post-smtp' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the settings option array and print one of its values
|
||||
*/
|
||||
public function redirect_url_callback() {
|
||||
$this->options = $this->options;
|
||||
$transport = $this;
|
||||
$oauthScribe = $transport->getScribe();
|
||||
printf( '<input type="text" onClick="this.setSelectionRange(0, this.value.length)" readonly="readonly" id="input_oauth_redirect_url" class="ps-input ps-w-75" value="%s" size="60"/>', $oauthScribe->getCallbackUrl() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the settings option array and print one of its values
|
||||
*/
|
||||
public function sender_email_callback() {
|
||||
$inputValue = (null !== $this->options->getEnvelopeSender() ? esc_attr( $this->options->getEnvelopeSender() ) : '');
|
||||
$requiredLabel = __( 'Required', 'post-smtp' );
|
||||
$envelopeFromMessage = __( 'This address, like the <b>return address</b> printed on an envelope, identifies the account owner to the SMTP server.', 'post-smtp' );
|
||||
$spfMessage = sprintf( __( 'For reliable delivery, this domain must specify an <a target="_blank" href="%s">SPF record</a> permitting the use of the SMTP server named above.', 'post-smtp' ), 'https://www.mail-tester.com/spf/' );
|
||||
printf( '<input type="email" id="input_envelope_sender_email" name="postman_options[envelope_sender]" value="%s" size="40" class="required" placeholder="%s"/> <br/><span class="postman_input_description">%s %s</span>', $inputValue, $requiredLabel, $envelopeFromMessage, $spfMessage );
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function printWizardMailServerHostnameStep() {
|
||||
printf( '<legend>%s</legend>', _x( 'Which host will relay the mail?', 'Wizard Step Title', 'post-smtp' ) );
|
||||
printf( '<p><label>%s</label></p>', __( 'If you want to use SendinBlue, Mandrill, Mailgun, SendGrid or other (API), You can skip this step by pressing next.', 'post-smtp' ) );
|
||||
printf( '<p>%s</p>', __( 'This is the Outgoing (SMTP) Mail Server, or Mail Submission Agent (MSA), which Postman delegates mail delivery to. This server is specific to your email account, and if you don\'t know what to use, ask your email service provider.', 'post-smtp' ) );
|
||||
printf( '<p><label>%s<label></p>', __( 'Note that many WordPress hosts, such as GoDaddy, Bluehost and Dreamhost, require that you use their mail accounts with their mail servers, and prevent you from using others.', 'post-smtp' ) );
|
||||
|
||||
//printf( '<div><strong><u>%s</u></strong></div><br>', __( 'If you plan to use An API and not SMTP just type any value.', 'post-smtp' ) );
|
||||
printf( '<label for="hostname">%s</label>', __( 'Outgoing Mail Server Hostname', 'post-smtp' ) );
|
||||
print $this->hostname_callback();
|
||||
printf( '<p class="ajax-loader" style="display:none"><img src="%s"/></p>', plugins_url( 'post-smtp/style/ajax-loader.gif' ) );
|
||||
$warning = __( 'Warning', 'post-smtp' );
|
||||
/* Translators: Where (%s) is the name of the web host */
|
||||
$nonGodaddyDomainMessage = sprintf( __( 'Your email address <b>requires</b> access to a remote SMTP server blocked by %s.', 'post-smtp' ), 'GoDaddy' );
|
||||
$nonGodaddyDomainMessage .= sprintf( ' %s', __( 'If you have access to cPanel, enable the Remote Mail Exchanger.', 'post-smtp' ) );
|
||||
printf( '<p id="godaddy_block"><span style="background-color:yellow"><b>%s</b>: %s</span></p>', $warning, $nonGodaddyDomainMessage );
|
||||
/* Translators: Where (%1$s) is the SPF-info URL and (%2$s) is the name of the web host */
|
||||
$godaddyCustomDomainMessage = sprintf( __( 'If you own this domain, make sure it has an <a href="%1$s">SPF record authorizing %2$s</a> as a relay, or you will have delivery problems.', 'post-smtp' ), 'http://www.mail-tester.com/spf/godaddy', 'GoDaddy' );
|
||||
$godaddy_note = __( 'Note: You may have delivery problems if you continue using the default outgoing mail server hostname.', 'post-smtp' );
|
||||
printf( '<div id="godaddy_spf_required"><p><span style="background-color:yellow"><b>%s</b>: %s</span></p><p class="ps-default-host-name"><label>%s<label></p></div>', $warning, $godaddyCustomDomainMessage, $godaddy_note );
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function printWizardAuthenticationStep() {
|
||||
print '<section class="wizard-auth-oauth2">';
|
||||
print '<p id="wizard_oauth2_help"></p>';
|
||||
printf( '<label id="callback_domain" for="callback_domain">%s</label>', $this->getScribe()->getCallbackDomainLabel() );
|
||||
print '<br />';
|
||||
print $this->callback_domain_callback();
|
||||
print '<br />';
|
||||
printf( '<label id="redirect_url" for="redirect_uri">%s</label>', $this->getScribe()->getCallbackUrlLabel() );
|
||||
print '<br />';
|
||||
print $this->redirect_url_callback();
|
||||
print '<br />';
|
||||
printf( '<label id="client_id" for="client_id">%s</label>', $this->getScribe()->getClientIdLabel() );
|
||||
print '<br />';
|
||||
print $this->oauth_client_id_callback();
|
||||
print '<br />';
|
||||
printf( '<label id="client_secret" for="client_secret">%s</label>', $this->getScribe()->getClientSecretLabel() );
|
||||
print '<br />';
|
||||
print $this->oauth_client_secret_callback();
|
||||
print '<br />';
|
||||
print '</section>';
|
||||
|
||||
print '<section class="wizard-auth-basic">';
|
||||
printf( '<p class="port-explanation-ssl">%s</p>', __( 'Enter the account credentials.', 'post-smtp' ) );
|
||||
printf( '<label for="username">%s</label>', __( 'Username', 'post-smtp' ) );
|
||||
print '<br />';
|
||||
print $this->basic_auth_username_callback();
|
||||
print '<br />';
|
||||
printf( '<label for="password">%s</label>', __( 'Password', 'post-smtp' ) );
|
||||
print '<br />';
|
||||
print $this->basic_auth_password_callback();
|
||||
print '</section>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true, to prevent from errors because it's default Module Transport.
|
||||
*
|
||||
* @since 2.1.4
|
||||
* @version 1.0
|
||||
*/
|
||||
public function has_granted() {
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Socket's logo
|
||||
*
|
||||
* @since 2.1
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getLogoURL() {
|
||||
|
||||
return POST_SMTP_ASSETS . "images/logos/smtp.png";
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,246 @@
|
||||
<?php
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
if( !class_exists( 'PostmanSparkPostMailEngine' ) ):
|
||||
|
||||
require_once 'Services/SparkPost/Handler.php';
|
||||
|
||||
class PostmanSparkPostMailEngine implements PostmanMailEngine {
|
||||
|
||||
protected $logger;
|
||||
|
||||
private $transcript;
|
||||
|
||||
private $api_key;
|
||||
|
||||
/**
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function __construct( $api_key ) {
|
||||
assert( !empty( $api_key ) );
|
||||
$this->api_key = $api_key;
|
||||
|
||||
// create the logger
|
||||
$this->logger = new PostmanLogger( get_class( $this ) );
|
||||
|
||||
}
|
||||
|
||||
public function getTranscript() {
|
||||
return $this->transcript;
|
||||
}
|
||||
|
||||
private function addAttachmentsToMail( PostmanMessage $message ) {
|
||||
|
||||
$attachments = $message->getAttachments();
|
||||
|
||||
if ( ! is_array( $attachments ) ) {
|
||||
// WordPress may a single filename or a newline-delimited string list of multiple filenames
|
||||
$attArray = explode( PHP_EOL, $attachments );
|
||||
} else {
|
||||
$attArray = $attachments;
|
||||
}
|
||||
// otherwise WordPress sends an array
|
||||
$attachments = array();
|
||||
foreach ( $attArray as $file ) {
|
||||
if ( ! empty( $file ) ) {
|
||||
$this->logger->debug( 'Adding attachment: ' . $file );
|
||||
|
||||
$file_name = basename( $file );
|
||||
$file_type = wp_check_filetype( $file );
|
||||
$attachments[] = array(
|
||||
'name' => $file_name,
|
||||
'type' => $file_type['type'],
|
||||
'data' => base64_encode( file_get_contents( $file ) )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $attachments;
|
||||
|
||||
}
|
||||
|
||||
public function send( PostmanMessage $message ) {
|
||||
|
||||
$options = PostmanOptions::getInstance();
|
||||
|
||||
if ( $this->logger->isDebug() ) {
|
||||
$this->logger->debug( 'Creating SparkPost service with api_key=' . $this->api_key );
|
||||
}
|
||||
|
||||
$spark_post = new PostmanSparkPost( $this->api_key );
|
||||
|
||||
$sender = $message->getFromAddress();
|
||||
$senderEmail = !empty( $sender->getEmail() ) ? $sender->getEmail() : $options->getMessageSenderEmail();
|
||||
$senderName = !empty( $sender->getName() ) ? $sender->getName() : $options->getMessageSenderName();
|
||||
|
||||
$sender->log( $this->logger, 'From' );
|
||||
|
||||
$body = [
|
||||
'content' => [
|
||||
'from' => [
|
||||
'name' => $senderName,
|
||||
'email' => $senderEmail,
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
$body['content']['subject'] = $message->getSubject();
|
||||
|
||||
$htmlPart = $message->getBodyHtmlPart();
|
||||
if ( ! empty( $htmlPart ) ) {
|
||||
$this->logger->debug( 'Adding body as html' );
|
||||
$body['content']['html'] = $htmlPart;
|
||||
}
|
||||
|
||||
$textPart = $message->getBodyTextPart();
|
||||
if ( ! empty( $textPart ) ) {
|
||||
$this->logger->debug( 'Adding body as text' );
|
||||
$body['content']['text'] = $textPart;
|
||||
}
|
||||
|
||||
// add attachments
|
||||
$this->logger->debug( 'Adding attachments' );
|
||||
|
||||
$attachments = $this->addAttachmentsToMail( $message );
|
||||
$body['content']['attachments'] = $attachments;
|
||||
|
||||
// Initialize recipient array
|
||||
|
||||
$tos = array();
|
||||
$duplicates = array();
|
||||
$to_emails = array();
|
||||
// add the to recipients
|
||||
foreach ( (array)$message->getToRecipients() as $recipient ) {
|
||||
$to_emails[] = $recipient->getEmail();
|
||||
if ( !array_key_exists( $recipient->getEmail(), $duplicates ) ) {
|
||||
|
||||
$tos[] = array(
|
||||
'address' => array(
|
||||
'email' => $recipient->getEmail()
|
||||
),
|
||||
);
|
||||
|
||||
$duplicates[] = $recipient->getEmail();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$body['recipients'] = $tos;
|
||||
|
||||
// Add cc
|
||||
$cc = array();
|
||||
$duplicates = array();
|
||||
foreach ( ( array ) $message->getCcRecipients() as $recipient ) {
|
||||
$cc_emails[] = $recipient->getEmail();
|
||||
if ( ! in_array( $recipient->getEmail(), $duplicates ) ) {
|
||||
$recipient->log($this->logger, 'Cc');
|
||||
$cc[] = array(
|
||||
'address' => array(
|
||||
'email' => $recipient->getEmail(),
|
||||
'header_to' => implode( ',', $to_emails )
|
||||
),
|
||||
);
|
||||
$duplicates[] = $recipient->getEmail();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Add bcc
|
||||
$bcc = array();
|
||||
$duplicates = array();
|
||||
foreach ( ( array ) $message->getBccRecipients() as $recipient ) {
|
||||
$bcc_emails[] = $recipient->getEmail();
|
||||
if ( ! in_array( $recipient->getEmail(), $duplicates ) ) {
|
||||
|
||||
$recipient->log($this->logger, 'Bcc');
|
||||
$bcc[] = array(
|
||||
'address' => array(
|
||||
'email' => $recipient->getEmail(),
|
||||
'header_to' => implode( ',', $to_emails )
|
||||
),
|
||||
);
|
||||
|
||||
$duplicates[] = $recipient->getEmail();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ( !empty( $cc ) && !empty( $bcc ) ) {
|
||||
$body['recipients'] = array_merge( $tos, $cc, $bcc );
|
||||
$body['content']['headers']['cc'] = implode( ',', $cc_emails );
|
||||
} elseif ( !empty( $cc ) ) {
|
||||
$body['recipients'] = array_merge( $tos, $cc );
|
||||
$body['content']['headers']['cc'] = implode( ',', $cc_emails );
|
||||
} elseif ( !empty( $bcc ) ) {
|
||||
$body['recipients'] = array_merge( $tos, $bcc );
|
||||
}
|
||||
|
||||
// add the reply-to
|
||||
$replyTo = $message->getReplyTo();
|
||||
// $replyTo is null or a PostmanEmailAddress object
|
||||
if ( isset( $replyTo ) ) {
|
||||
$body['content']['reply_to'] = $replyTo->getEmail();
|
||||
}
|
||||
|
||||
// add the Postman signature - append it to whatever the user may have set
|
||||
if ( ! $options->isStealthModeEnabled() ) {
|
||||
$pluginData = apply_filters( 'postman_get_plugin_metadata', null );
|
||||
$headers['X-Mailer'] = sprintf( 'Postman SMTP %s for WordPress (%s)', $pluginData ['version'], 'https://wordpress.org/plugins/post-smtp/' );
|
||||
}
|
||||
|
||||
foreach ( ( array ) $message->getHeaders() as $header ) {
|
||||
$this->logger->debug( sprintf( 'Adding user header %s=%s', $header ['name'], $header ['content'] ) );
|
||||
$headers[$header['name']] = $header ['content'];
|
||||
}
|
||||
|
||||
// add the messageId
|
||||
$messageId = $message->getMessageId();
|
||||
if ( ! empty( $messageId ) ) {
|
||||
$headers['message-id'] = $messageId;
|
||||
}
|
||||
|
||||
$body['headers'] = $headers;
|
||||
|
||||
// if the caller set a Content-Type header, use it
|
||||
$contentType = $message->getContentType();
|
||||
if ( ! empty( $contentType ) ) {
|
||||
$this->logger->debug( 'Some header keys are reserved. You may not include any of the following reserved headers: x-sg-id, x-sg-eid, received, dkim-signature, Content-Type, Content-Transfer-Encoding, To, From, Subject, Reply-To, CC, BCC.' );
|
||||
}
|
||||
|
||||
//Send Email
|
||||
try {
|
||||
$response = $spark_post->send( $body );
|
||||
|
||||
if ( $this->logger->isDebug() ) {
|
||||
|
||||
$this->logger->debug( 'Sending mail' );
|
||||
|
||||
}
|
||||
|
||||
|
||||
$this->transcript = print_r( $response, true );
|
||||
$this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
|
||||
$this->transcript .= print_r( $body, true );
|
||||
$this->logger->debug( 'Transcript=' . $this->transcript );
|
||||
|
||||
} catch ( Exception $e ) {
|
||||
|
||||
$this->transcript = $e->getMessage();
|
||||
$this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS;
|
||||
$this->transcript .= print_r( $body, true );
|
||||
$this->logger->debug( 'Transcript=' . $this->transcript );
|
||||
|
||||
throw $e;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
endif;
|
||||
@@ -0,0 +1,316 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once 'PostmanModuleTransport.php';
|
||||
|
||||
/**
|
||||
* Postman SparkPost
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
if( !class_exists( 'PostmanSparkPostTransport' ) ):
|
||||
class PostmanSparkPostTransport extends PostmanAbstractModuleTransport implements PostmanModuleTransport {
|
||||
|
||||
const SLUG = 'sparkpost_api';
|
||||
const PORT = 587;
|
||||
const HOST = 'smtp.sparkpostmail.com';
|
||||
const PRIORITY = 45000;
|
||||
const SPARKPOST_AUTH_OPTIONS = 'postman_sparkpost_auth_options';
|
||||
const SPARKPOST_AUTH_SECTION = 'postman_sparkpost_auth_section';
|
||||
|
||||
/**
|
||||
* PostmanSparkPostTransport constructor.
|
||||
* @param $rootPluginFilenameAndPath
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function __construct( $rootPluginFilenameAndPath ) {
|
||||
|
||||
parent::__construct ( $rootPluginFilenameAndPath );
|
||||
|
||||
// add a hook on the plugins_loaded event
|
||||
add_action ( 'admin_init', array ( $this, 'on_admin_init' ) );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getPort() {
|
||||
return self::PORT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getSlug() {
|
||||
return self::SLUG;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getProtocol() {
|
||||
return 'https';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getHostname() {
|
||||
return self::HOST;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getConfigurationBid( PostmanWizardSocket $hostData, $userAuthOverride, $originalSmtpServer ) {
|
||||
|
||||
$recommendation = array();
|
||||
$recommendation ['priority'] = 0;
|
||||
$recommendation ['transport'] = self::SLUG;
|
||||
$recommendation ['hostname'] = null; // scribe looks this
|
||||
$recommendation ['label'] = $this->getName();
|
||||
$recommendation['logo_url'] = $this->getLogoURL();
|
||||
|
||||
if ($hostData->hostname == self::HOST && $hostData->port == self::PORT) {
|
||||
$recommendation ['priority'] = self::PRIORITY;
|
||||
/* translators: where variables are (1) transport name (2) host and (3) port */
|
||||
$recommendation ['message'] = sprintf ( __ ( ('Postman recommends the %1$s to host %2$s on port %3$d.') ), $this->getName(), self::HOST, self::PORT );
|
||||
}
|
||||
|
||||
return $recommendation;
|
||||
|
||||
}
|
||||
|
||||
public function createMailEngine() {
|
||||
|
||||
$api_key = $this->options->getSparkPostApiKey();
|
||||
require_once 'PostmanSparkPostMailEngine.php';
|
||||
$engine = new PostmanSparkPostMailEngine( $api_key );
|
||||
|
||||
return $engine;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getName() {
|
||||
|
||||
return __( 'SparkPost', 'post-smtp' );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getDeliveryDetails() {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PostmanWizardSocket $socket
|
||||
* @param $winningRecommendation
|
||||
* @param $userSocketOverride
|
||||
* @param $userAuthOverride
|
||||
* @return array
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function createOverrideMenu( PostmanWizardSocket $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride ) {
|
||||
|
||||
$overrideItem = parent::createOverrideMenu ( $socket, $winningRecommendation, $userSocketOverride, $userAuthOverride );
|
||||
|
||||
// push the authentication options into the $overrideItem structure
|
||||
$overrideItem ['auth_items'] = array (
|
||||
array (
|
||||
'selected' => true,
|
||||
'name' => __ ( 'API Key', 'post-smtp' ),
|
||||
'value' => 'api_key'
|
||||
)
|
||||
);
|
||||
|
||||
return $overrideItem;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function on_admin_init() {
|
||||
|
||||
if( PostmanUtils::isAdmin() ) {
|
||||
|
||||
$this->addSettings();
|
||||
$this->registerStylesAndScripts();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function addSettings()
|
||||
{
|
||||
|
||||
add_settings_section(
|
||||
self::SPARKPOST_AUTH_SECTION,
|
||||
__('Authentication', 'post-smtp'),
|
||||
array( $this, 'printSparkPostAuthSectionInfo' ),
|
||||
self::SPARKPOST_AUTH_OPTIONS
|
||||
);
|
||||
|
||||
add_settings_field(
|
||||
PostmanOptions::SPARKPOST_API_KEY,
|
||||
__( 'API Token', 'post-smtp' ),
|
||||
array( $this, 'sparkpost_api_key_callback' ),
|
||||
self::SPARKPOST_AUTH_OPTIONS,
|
||||
self::SPARKPOST_AUTH_SECTION
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function printSparkPostAuthSectionInfo() {
|
||||
|
||||
printf (
|
||||
'<p id="wizard_sparkpost_auth_help">%s</p>', sprintf ( __ ( 'Create an account at <a href="%1$s" target="_blank">%2$s</a> and enter <a href="%3$s" target="_blank">an API Key</a> below.', 'post-smtp' ),
|
||||
'https://app.sparkpost.com/join', 'SparkPost', 'https://app.sparkpost.com/account/api-keys' )
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function sparkpost_api_key_callback() {
|
||||
|
||||
printf ( '<input type="password" autocomplete="off" id="sparkpost_api_key" name="postman_options[sparkpost_api_key]" value="%s" size="60" class="required ps-input ps-w-75" placeholder="%s"/>', null !== $this->options->getSparkPostApiKey() ? esc_attr ( PostmanUtils::obfuscatePassword ( $this->options->getSparkPostApiKey() ) ) : '', __ ( 'Required', 'post-smtp' ) );
|
||||
print ' <input type="button" id="toggleSparkPostApiKey" value="Show Password" class="button button-secondary" style="visibility:hidden" />';
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function registerStylesAndScripts() {
|
||||
|
||||
$pluginData = apply_filters( 'postman_get_plugin_metadata', null );
|
||||
|
||||
wp_register_script (
|
||||
'postman-sparkpost',
|
||||
plugins_url ( 'Postman/Postman-Mail/postman-sparkpost.js', $this->rootPluginFilenameAndPath ),
|
||||
array (
|
||||
PostmanViewController::JQUERY_SCRIPT,
|
||||
'jquery_validation',
|
||||
PostmanViewController::POSTMAN_SCRIPT
|
||||
),
|
||||
$pluginData['version']
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function enqueueScript() {
|
||||
|
||||
wp_enqueue_script( 'postman-sparkpost' );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function printWizardAuthenticationStep() {
|
||||
print '<section class="wizard_sparkpost">';
|
||||
$this->printSparkPostAuthSectionInfo();
|
||||
printf ( '<label for="api_key">%s</label>', __ ( 'API Key', 'post-smtp' ) );
|
||||
print '<br />';
|
||||
print $this->sparkpost_api_key_callback();
|
||||
print '
|
||||
<div class="sparkpost-documentation">
|
||||
<div>
|
||||
<iframe width="300" height="200" src="https://www.youtube.com/embed/-uVVGvsAZ_E" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
</div>
|
||||
<div>
|
||||
<a href="https://postmansmtp.com/documentation/#configure-sparkpost-integration" target="_blank">Stuck in Setup?</a>
|
||||
</div>
|
||||
</div>';
|
||||
print '</section>';
|
||||
}
|
||||
|
||||
/**
|
||||
* (non-PHPdoc)
|
||||
*
|
||||
* @see PostmanTransport::getMisconfigurationMessage()
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
protected function validateTransportConfiguration() {
|
||||
$messages = parent::validateTransportConfiguration ();
|
||||
$apiKey = $this->options->getSparkPostApiKey ();
|
||||
if (empty ( $apiKey )) {
|
||||
array_push ( $messages, __ ( 'API Key can not be empty', 'post-smtp' ) . '.' );
|
||||
$this->setNotConfiguredAndReady ();
|
||||
}
|
||||
if (! $this->isSenderConfigured ()) {
|
||||
array_push ( $messages, __ ( 'Message From Address can not be empty', 'post-smtp' ) . '.' );
|
||||
$this->setNotConfiguredAndReady ();
|
||||
}
|
||||
return $messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true, to prevent from errors because it's default Module Transport.
|
||||
*
|
||||
* @since 2.1.8
|
||||
* @version 1.0
|
||||
*/
|
||||
public function has_granted() {
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Socket's logo
|
||||
*
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function getLogoURL() {
|
||||
|
||||
return POST_SMTP_ASSETS . "images/logos/sparkpost.png";
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
endif;
|
||||
@@ -0,0 +1,243 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly.
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'PostmanSweegoMailEngine' ) ) {
|
||||
|
||||
require_once 'Services/Sweego/Handler.php';
|
||||
|
||||
/**
|
||||
* Sends mail with the Sweego API.
|
||||
*/
|
||||
class PostmanSweegoMailEngine implements PostmanMailEngine {
|
||||
|
||||
protected $logger;
|
||||
private $transcript;
|
||||
private $apiKey;
|
||||
|
||||
public function __construct( $apiKey ) {
|
||||
assert( ! empty( $apiKey ) );
|
||||
$this->apiKey = $apiKey;
|
||||
$this->logger = new PostmanLogger( get_class( $this ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an email via Sweego, including attachments if provided.
|
||||
*
|
||||
* @param PostmanMessage $message The message object.
|
||||
* @return void
|
||||
* @throws Exception On error.
|
||||
*/
|
||||
public function send( PostmanMessage $message ) {
|
||||
$options = PostmanOptions::getInstance();
|
||||
$sweego = new PostmanSweego( $this->apiKey );
|
||||
|
||||
$recipients = [];
|
||||
$duplicates = []; // Sender.
|
||||
$sender = $message->getFromAddress();
|
||||
$senderEmail = ! empty( $sender->getEmail() ) ? $sender->getEmail() : $options->getMessageSenderEmail();
|
||||
$senderName = ! empty( $sender->getName() ) ? $sender->getName() : $options->getMessageSenderName();
|
||||
$sender->log( $this->logger, 'From' );
|
||||
|
||||
// Recipients.
|
||||
foreach ( (array) $message->getToRecipients() as $recipient ) {
|
||||
if ( ! in_array( $recipient->getEmail(), $duplicates ) ) {
|
||||
$recipients[] = $recipient->getEmail();
|
||||
$duplicates[] = $recipient->getEmail();
|
||||
}
|
||||
}
|
||||
|
||||
// Subject and Body.
|
||||
$subject = $message->getSubject();
|
||||
$textPart = $message->getBodyTextPart();
|
||||
$htmlPart = $message->getBodyHtmlPart();
|
||||
$htmlContent = ! empty( $htmlPart ) ? $htmlPart : nl2br( $textPart );
|
||||
|
||||
if ( empty( $htmlContent ) ) {
|
||||
$htmlContent = '<p>(No content)</p>';
|
||||
}
|
||||
|
||||
// Prepare content for Sweego API
|
||||
$content = [
|
||||
'provider' => 'string',
|
||||
'campaign-type' => 'market',
|
||||
'from' => [
|
||||
'email' => $senderEmail,
|
||||
'name' => $senderName,
|
||||
],
|
||||
'recipients' => [],
|
||||
'subject' => $subject,
|
||||
'message-html' => $htmlContent,
|
||||
'message-txt' => wp_strip_all_tags( $textPart ?: $htmlPart ),
|
||||
];
|
||||
|
||||
// Add recipients
|
||||
foreach ( (array) $message->getToRecipients() as $recipient ) {
|
||||
$content['recipients'][] = [
|
||||
'email' => $recipient->getEmail(),
|
||||
'name' => $recipient->getName() ?: '',
|
||||
];
|
||||
}
|
||||
|
||||
// Add CC recipients if any
|
||||
$ccRecipients = $message->getCcRecipients();
|
||||
if ( ! empty( $ccRecipients ) ) {
|
||||
$content['cc'] = [];
|
||||
foreach ( $ccRecipients as $ccRecipient ) {
|
||||
$content['cc'][] = [
|
||||
'email' => $ccRecipient->getEmail(),
|
||||
'name' => $ccRecipient->getName() ?: '',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// Add BCC recipients if any
|
||||
$bccRecipients = $message->getBccRecipients();
|
||||
if ( ! empty( $bccRecipients ) ) {
|
||||
$content['bcc'] = [];
|
||||
foreach ( $bccRecipients as $bccRecipient ) {
|
||||
$content['bcc'][] = [
|
||||
'email' => $bccRecipient->getEmail(),
|
||||
'name' => $bccRecipient->getName() ?: '',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// Add Reply-To if set
|
||||
$replyTo = $message->getReplyTo();
|
||||
if ( $replyTo ) {
|
||||
$content['replyTo'] = [
|
||||
'email' => $replyTo->getEmail(),
|
||||
'name' => $replyTo->getName() ?: '',
|
||||
];
|
||||
} // Attachments.
|
||||
$attachments = $this->addAttachmentsToMail( $message );
|
||||
if ( ! empty( $attachments ) ) {
|
||||
$content['attachments'] = $attachments;
|
||||
}
|
||||
|
||||
// Send.
|
||||
try {
|
||||
$this->logger->debug( 'Sending mail via Sweego' );
|
||||
|
||||
// Make API call using Sweego Handler
|
||||
$response = $sweego->send( $content );
|
||||
$responseCode = $sweego->get_response_code();
|
||||
$responseBody = $sweego->get_response_body();
|
||||
|
||||
// Log the response for debugging
|
||||
$this->logger->debug( 'Sweego API Response Code: ' . $responseCode );
|
||||
$this->logger->debug( 'Sweego API Response Body: ' . $responseBody );
|
||||
|
||||
if ( $responseCode === 200 || $responseCode === 202 ) {
|
||||
$this->transcript = 'Email sent successfully via Sweego API.' . PHP_EOL;
|
||||
$this->transcript .= 'Response Code: ' . $responseCode . PHP_EOL;
|
||||
$this->transcript .= 'Response: ' . $responseBody . PHP_EOL;
|
||||
$this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS . PHP_EOL;
|
||||
$this->transcript .= print_r( $content, true );
|
||||
$this->logger->debug( 'Transcript=' . $this->transcript );
|
||||
} else {
|
||||
$decodedBody = json_decode( $responseBody, true );
|
||||
$errorMessage = $this->extractErrorMessage( $decodedBody, $responseCode );
|
||||
$this->logger->error( 'Sweego API Error: ' . $errorMessage );
|
||||
throw new Exception( $errorMessage );
|
||||
}
|
||||
} catch ( Exception $e ) {
|
||||
$this->transcript = $e->getMessage() . PHP_EOL;
|
||||
$this->transcript .= PostmanModuleTransport::RAW_MESSAGE_FOLLOWS . PHP_EOL;
|
||||
$this->transcript .= print_r( $content, true );
|
||||
$this->logger->debug( 'Transcript=' . $this->transcript );
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares attachments for the API.
|
||||
*
|
||||
* @param PostmanMessage $message The message object.
|
||||
* @return array
|
||||
*/
|
||||
private function addAttachmentsToMail( PostmanMessage $message ) {
|
||||
$attachments = $message->getAttachments();
|
||||
$attArray = is_array( $attachments ) ? $attachments : explode( PHP_EOL, $attachments );
|
||||
$result = [];
|
||||
|
||||
foreach ( $attArray as $file ) {
|
||||
if ( ! empty( $file ) ) {
|
||||
$this->logger->debug( 'Adding attachment: ' . $file );
|
||||
$fileName = basename( $file );
|
||||
$fileType = wp_check_filetype( $file );
|
||||
$result[] = [
|
||||
'content' => base64_encode( file_get_contents( $file ) ),
|
||||
'type' => $fileType['type'],
|
||||
'filename' => $fileName,
|
||||
'disposition' => 'attachment',
|
||||
'name' => pathinfo( $fileName, PATHINFO_FILENAME ),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return debug transcript.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getTranscript() {
|
||||
return $this->transcript;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the error message from a JSON-decoded response.
|
||||
*
|
||||
* @param array $decodedBody The response body.
|
||||
* @param int $responseCode HTTP code.
|
||||
* @return string
|
||||
*/
|
||||
private function extractErrorMessage( $decodedBody, $responseCode ) {
|
||||
if ( is_array( $decodedBody ) ) {
|
||||
if ( isset( $decodedBody['message'] ) && is_string( $decodedBody['message'] ) ) {
|
||||
return $decodedBody['message'];
|
||||
}
|
||||
if ( isset( $decodedBody['error'] ) ) {
|
||||
return is_string( $decodedBody['error'] )
|
||||
? $decodedBody['error']
|
||||
: ( $decodedBody['error']['message'] ?? $this->getErrorMessageFromCode( $responseCode ) );
|
||||
}
|
||||
}
|
||||
|
||||
return $this->getErrorMessageFromCode( $responseCode );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a user-friendly error message based on HTTP response code.
|
||||
*
|
||||
* @param int $response_code HTTP status code returned by the Sweego API.
|
||||
* @return string Translated error message.
|
||||
*/
|
||||
private function getErrorMessageFromCode( $response_code ) {
|
||||
switch ( $response_code ) {
|
||||
case 400:
|
||||
return __( 'Bad request. Please check your email data.', 'post-smtp' );
|
||||
case 401:
|
||||
return __( 'Unauthorized. Please check your API key.', 'post-smtp' );
|
||||
case 403:
|
||||
return __( 'Forbidden. Access denied.', 'post-smtp' );
|
||||
case 404:
|
||||
return __( 'Not found. Please check the API endpoint.', 'post-smtp' );
|
||||
case 422:
|
||||
return __( 'Domain verification required. Your sending domain must be verified in Sweego before you can send emails. Please verify your domain in your Sweego dashboard.', 'post-smtp' );
|
||||
case 429:
|
||||
return __( 'Rate limit exceeded. Please try again later.', 'post-smtp' );
|
||||
case 500:
|
||||
return __( 'Internal server error. Please try again later.', 'post-smtp' );
|
||||
default:
|
||||
// translators: %d is the HTTP error code.
|
||||
return sprintf( __( 'HTTP error %d occurred.', 'post-smtp' ), $response_code );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
require_once 'PostmanModuleTransport.php';
|
||||
/**
|
||||
* Postman Sweego module
|
||||
*/
|
||||
class PostmanSweegoTransport extends PostmanAbstractModuleTransport implements PostmanModuleTransport {
|
||||
const SLUG = 'sweego_api';
|
||||
const PORT = 443;
|
||||
const HOST = 'api.sweego.com'; // Change to actual Sweego API host if different
|
||||
const PRIORITY = 48011;
|
||||
const SWEEGO_AUTH_OPTIONS = 'postman_sweego_auth_options';
|
||||
const SWEEGO_AUTH_SECTION = 'postman_sweego_auth_section';
|
||||
|
||||
public function __construct($rootPluginFilenameAndPath) {
|
||||
parent::__construct($rootPluginFilenameAndPath);
|
||||
add_action('admin_init', array($this, 'on_admin_init'));
|
||||
}
|
||||
public function getProtocol() {
|
||||
return 'https';
|
||||
}
|
||||
public function getSlug() {
|
||||
return self::SLUG;
|
||||
}
|
||||
public function getName() {
|
||||
return __('Sweego', 'post-smtp');
|
||||
}
|
||||
public function getHostname() {
|
||||
return self::HOST;
|
||||
}
|
||||
public function getPort() {
|
||||
return self::PORT;
|
||||
}
|
||||
public function getTransportType() {
|
||||
return 'Sweego_api';
|
||||
}
|
||||
public function createMailEngine() {
|
||||
$apiKey = $this->options->getSweegoApiKey();
|
||||
require_once 'PostmanSweegoMailEngine.php';
|
||||
$engine = new PostmanSweegoMailEngine($apiKey);
|
||||
return $engine;
|
||||
}
|
||||
public function getDeliveryDetails() {
|
||||
return sprintf(__('Postman will send mail via the <b>%1$s %2$s</b>.', 'post-smtp'), '🔐', $this->getName());
|
||||
}
|
||||
protected function validateTransportConfiguration() {
|
||||
$messages = parent::validateTransportConfiguration();
|
||||
$apiKey = $this->options->getSweegoApiKey();
|
||||
if (empty($apiKey)) {
|
||||
array_push($messages, __('API Key can not be empty', 'post-smtp') . '.');
|
||||
$this->setNotConfiguredAndReady();
|
||||
}
|
||||
if (!$this->isSenderConfigured()) {
|
||||
array_push($messages, __('Message From Address can not be empty', 'post-smtp') . '.');
|
||||
$this->setNotConfiguredAndReady();
|
||||
}
|
||||
return $messages;
|
||||
}
|
||||
public function getConfigurationBid(PostmanWizardSocket $hostData, $userAuthOverride, $originalSmtpServer) {
|
||||
$recommendation = array();
|
||||
$recommendation['priority'] = 0;
|
||||
$recommendation['transport'] = self::SLUG;
|
||||
$recommendation['hostname'] = null;
|
||||
$recommendation['label'] = $this->getName();
|
||||
$recommendation['logo_url'] = $this->getLogoURL();
|
||||
if ($hostData->hostname == self::HOST && $hostData->port == self::PORT) {
|
||||
$recommendation['priority'] = self::PRIORITY;
|
||||
$recommendation['message'] = sprintf(__('Postman recommends the %1$s to host %2$s on port %3$d.'), $this->getName(), self::HOST, self::PORT);
|
||||
}
|
||||
return $recommendation;
|
||||
}
|
||||
public function on_admin_init() {
|
||||
if (PostmanUtils::isAdmin()) {
|
||||
$this->addSettings();
|
||||
$this->registerStylesAndScripts();
|
||||
}
|
||||
}
|
||||
public function addSettings() {
|
||||
add_settings_section(self::SWEEGO_AUTH_SECTION, __('Authentication', 'post-smtp'), array($this, 'printSweegoAuthSectionInfo'), self::SWEEGO_AUTH_OPTIONS);
|
||||
add_settings_field('sweego_api_key', __('API Key', 'post-smtp'), array($this, 'sweego_api_key_callback'), self::SWEEGO_AUTH_OPTIONS, self::SWEEGO_AUTH_SECTION);
|
||||
}
|
||||
public function printSweegoAuthSectionInfo() {
|
||||
printf('<p id="wizard_sweego_auth_help">%s</p>', sprintf(__('Enter your Sweego API key and endpoint below.', 'post-smtp')));
|
||||
}
|
||||
public function sweego_api_key_callback() {
|
||||
printf('<input type="password" autocomplete="off" id="sweego_api_key" name="postman_options[sweego_api_key]" value="%s" size="60" class="required ps-input ps-w-75" placeholder="%s"/>', null !== $this->options->getSweegoApiKey() ? esc_attr(PostmanUtils::obfuscatePassword($this->options->getSweegoApiKey())) : '', __('Required', 'post-smtp'));
|
||||
print ' <input type="button" id="toggleSweegoApiKey" value="Show Password" class="button button-secondary" style="visibility:hidden" />';
|
||||
}
|
||||
public function registerStylesAndScripts() {
|
||||
// register the stylesheet and javascript external resources
|
||||
$pluginData = apply_filters( 'postman_get_plugin_metadata', null );
|
||||
wp_register_script(
|
||||
'postman-sweego',
|
||||
plugins_url( 'Postman/Postman-Mail/postman-sweego.js', $this->rootPluginFilenameAndPath ),
|
||||
array(
|
||||
PostmanViewController::JQUERY_SCRIPT,
|
||||
'jquery_validation',
|
||||
PostmanViewController::POSTMAN_SCRIPT
|
||||
),
|
||||
$pluginData['version']
|
||||
);
|
||||
}
|
||||
public function enqueueScript() {
|
||||
wp_enqueue_script( 'postman-sweego' );
|
||||
}
|
||||
public function printWizardAuthenticationStep() {
|
||||
print '<section class="wizard_sweego">';
|
||||
$this->printSweegoAuthSectionInfo();
|
||||
printf('<label for="api_key">%s</label>', __('API Key', 'post-smtp'));
|
||||
print '<br />';
|
||||
print $this->sweego_api_key_callback();
|
||||
print '</section>';
|
||||
}
|
||||
public function getLogoURL() {
|
||||
return POST_SMTP_ASSETS . "images/logos/sweego.png";
|
||||
}
|
||||
public function has_granted() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,278 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
require_once 'PostmanModuleTransport.php';
|
||||
require_once 'PostmanZendMailTransportConfigurationFactory.php';
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jasonhendriks
|
||||
*/
|
||||
class PostmanTransportRegistry {
|
||||
private $transports;
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
*/
|
||||
private function __construct() {
|
||||
$this->logger = new PostmanLogger( get_class( $this ) );
|
||||
}
|
||||
|
||||
// singleton instance
|
||||
public static function getInstance() {
|
||||
static $inst = null;
|
||||
if ( $inst === null ) {
|
||||
$inst = new PostmanTransportRegistry();
|
||||
}
|
||||
return $inst;
|
||||
}
|
||||
public function registerTransport( PostmanModuleTransport $instance ) {
|
||||
$this->transports [ $instance->getSlug() ] = $instance;
|
||||
$instance->init();
|
||||
}
|
||||
public function getTransports() {
|
||||
return $this->transports;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a Transport by slug
|
||||
* Look up a specific Transport use:
|
||||
* A) when retrieving the transport saved in the database
|
||||
* B) when querying what a theoretical scenario involving this transport is like
|
||||
* (ie.for ajax in config screen)
|
||||
*
|
||||
* @param mixed $slug
|
||||
*/
|
||||
public function getTransport( $slug ) {
|
||||
$transports = $this->getTransports();
|
||||
if ( isset( $transports [ $slug ] ) ) {
|
||||
return $transports [ $slug ];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A short-hand way of showing the complete delivery method
|
||||
*
|
||||
* @param PostmanModuleTransport $transport
|
||||
* @return string
|
||||
*/
|
||||
public function getPublicTransportUri( PostmanModuleTransport $transport ) {
|
||||
return $transport->getPublicTransportUri();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a specific transport is registered in the directory.
|
||||
*
|
||||
* @param mixed $slug
|
||||
*/
|
||||
public function isRegistered( $slug ) {
|
||||
$transports = $this->getTransports();
|
||||
return isset( $transports [ $slug ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the transport Postman is currently configured with.
|
||||
*
|
||||
* @return PostmanModuleTransport
|
||||
* @deprecated 2.1.4 use getActiveTransport()
|
||||
* @see getActiveTransport()
|
||||
*/
|
||||
public function getCurrentTransport() {
|
||||
$selectedTransport = PostmanOptions::getInstance()->getTransportType();
|
||||
$transports = $this->getTransports();
|
||||
if ( ! isset( $transports [ $selectedTransport ] ) ) {
|
||||
return $transports ['default'];
|
||||
} else {
|
||||
return $transports [ $selectedTransport ];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param PostmanOptions $options
|
||||
* @param PostmanOAuthToken $token
|
||||
* @return boolean
|
||||
*/
|
||||
public function getActiveTransport() {
|
||||
// During fallback mode, always use SMTP transport
|
||||
$options = PostmanOptions::getInstance();
|
||||
if ( $options->is_fallback ) {
|
||||
$transports = $this->getTransports();
|
||||
if ( isset( $transports['smtp'] ) ) {
|
||||
return $transports['smtp'];
|
||||
} else {
|
||||
return $transports['default'];
|
||||
}
|
||||
}
|
||||
|
||||
$selectedTransport = PostmanOptions::getInstance()->getTransportType();
|
||||
|
||||
$transports = $this->getTransports();
|
||||
if ( isset( $transports [ $selectedTransport ] ) ) {
|
||||
$transport = $transports [ $selectedTransport ];
|
||||
if ( $transport->getSlug() == $selectedTransport && $transport->isConfiguredAndReady() ) {
|
||||
return $transport;
|
||||
}
|
||||
}
|
||||
return $transports ['default'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the transport Postman is currently configured with.
|
||||
*
|
||||
* @return PostmanModuleTransport
|
||||
*/
|
||||
public function getSelectedTransport() {
|
||||
$selectedTransport = PostmanOptions::getInstance()->getTransportType();
|
||||
$transports = $this->getTransports();
|
||||
if ( isset( $transports [ $selectedTransport ] ) ) {
|
||||
return $transports [ $selectedTransport ];
|
||||
} else {
|
||||
return $transports ['default'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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::getSelectedTransport()->isOAuthUsed( $options->getAuthenticationType() );
|
||||
|
||||
// is the transport configured
|
||||
if ( $oauthUsed ) {
|
||||
$configured = self::getSelectedTransport()->isConfiguredAndReady();
|
||||
}
|
||||
|
||||
return $oauthUsed && $configured;
|
||||
}
|
||||
|
||||
/**
|
||||
* Polls all the installed transports to get a complete list of sockets to probe for connectivity
|
||||
*
|
||||
* @param mixed $hostname
|
||||
* @param mixed $isGmail
|
||||
* @return multitype:
|
||||
*/
|
||||
public function getSocketsForSetupWizardToProbe( $hostname = 'localhost', $smtpServerGuess = null ) {
|
||||
$hosts = array();
|
||||
if ( $this->logger->isDebug() ) {
|
||||
$this->logger->debug( sprintf( 'Getting sockets for Port Test given hostname %s and smtpServerGuess %s', $hostname, $smtpServerGuess ) );
|
||||
}
|
||||
|
||||
$transports = $this->getTransports();
|
||||
if ( $hostname !== 'smtp.gmail.com' ) {
|
||||
unset( $transports['gmail_api'] );
|
||||
}
|
||||
foreach ( $transports as $transport ) {
|
||||
$socketsToTest = $transport->getSocketsForSetupWizardToProbe( $hostname, $smtpServerGuess );
|
||||
if ( $this->logger->isTrace() ) {
|
||||
$this->logger->trace( 'sockets to test:' );
|
||||
$this->logger->trace( $socketsToTest );
|
||||
}
|
||||
$hosts = array_merge( $hosts, $socketsToTest );
|
||||
if ( $this->logger->isDebug() ) {
|
||||
$this->logger->debug( sprintf( 'Transport %s returns %d sockets ', $transport->getName(), sizeof( $socketsToTest ) ) );
|
||||
}
|
||||
}
|
||||
return $hosts;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the host port is a possible configuration option, recommend it
|
||||
*
|
||||
* $hostData includes ['host'] and ['port']
|
||||
*
|
||||
* response should include ['success'], ['message'], ['priority']
|
||||
*
|
||||
* @param mixed $hostData
|
||||
*/
|
||||
public function getRecommendation( PostmanWizardSocket $hostData, $userAuthOverride, $originalSmtpServer ) {
|
||||
$scrubbedUserAuthOverride = $this->scrubUserOverride( $hostData, $userAuthOverride );
|
||||
$transport = $this->getTransport( $hostData->transport );
|
||||
$recommendation = $transport->getConfigurationBid( $hostData, $scrubbedUserAuthOverride, $originalSmtpServer );
|
||||
if ( $this->logger->isDebug() ) {
|
||||
$this->logger->debug( sprintf( 'Transport %s bid %s', $transport->getName(), $recommendation ['priority'] ) );
|
||||
}
|
||||
return $recommendation;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param PostmanWizardSocket $hostData
|
||||
* @param mixed $userAuthOverride
|
||||
* @return NULL
|
||||
*/
|
||||
private function scrubUserOverride( PostmanWizardSocket $hostData, $userAuthOverride ) {
|
||||
$this->logger->trace( 'before scrubbing userAuthOverride: ' . $userAuthOverride );
|
||||
|
||||
// validate userAuthOverride
|
||||
if ( ! ($userAuthOverride == 'oauth2' || $userAuthOverride == 'password' || $userAuthOverride == 'none') ) {
|
||||
$userAuthOverride = null;
|
||||
}
|
||||
|
||||
// validate the userAuthOverride
|
||||
if ( ! $hostData->auth_xoauth ) {
|
||||
if ( $userAuthOverride == 'oauth2' ) {
|
||||
$userAuthOverride = null;
|
||||
}
|
||||
}
|
||||
if ( ! $hostData->auth_crammd5 && ! $hostData->authPlain && ! $hostData->auth_login ) {
|
||||
if ( $userAuthOverride == 'password' ) {
|
||||
$userAuthOverride = null;
|
||||
}
|
||||
}
|
||||
if ( ! $hostData->auth_none ) {
|
||||
if ( $userAuthOverride == 'none' ) {
|
||||
$userAuthOverride = null;
|
||||
}
|
||||
}
|
||||
$this->logger->trace( 'after scrubbing userAuthOverride: ' . $userAuthOverride );
|
||||
return $userAuthOverride;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public function getReadyMessage() {
|
||||
|
||||
$message = array();
|
||||
|
||||
if ( $this->getCurrentTransport()->isConfiguredAndReady() ) {
|
||||
if ( PostmanOptions::getInstance()->getRunMode() != PostmanOptions::RUN_MODE_PRODUCTION ) {
|
||||
$message = array(
|
||||
'error' => true,
|
||||
'message' => __( 'Postman is in <em>non-Production</em> mode and is dumping all emails.', 'post-smtp' ),
|
||||
);
|
||||
} else {
|
||||
$message = array(
|
||||
'error' => false,
|
||||
'message' => __( 'Postman is configured.', 'post-smtp' ),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$message = array(
|
||||
'error' => true,
|
||||
'message' => __( 'Postman is <em>not</em> configured and is mimicking out-of-the-box WordPress email delivery.', 'post-smtp' ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters Dashobard Notice
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @version 1.0.0
|
||||
*/
|
||||
return apply_filters( 'post_smtp_dashboard_notice', $message );
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'PostmanWoocommerce' ) ) {
|
||||
class PostmanWoocommerce {
|
||||
|
||||
private $options;
|
||||
|
||||
public function __construct() {
|
||||
$this->set_vars();
|
||||
$this->hooks();
|
||||
}
|
||||
|
||||
public function set_vars() {
|
||||
$this->options = PostmanOptions::getInstance ();
|
||||
}
|
||||
|
||||
public function hooks() {
|
||||
add_filter( 'option_woocommerce_email_from_address', array( $this, 'set_postman_from_address' ), 10, 2 );
|
||||
add_filter( 'woocommerce_email_from_address', array( $this, 'set_postman_from_address' ), 10, 2 );
|
||||
add_filter( 'woocommerce_get_settings_email', array( $this, 'overide_email_settings' ) );
|
||||
}
|
||||
|
||||
public function set_postman_from_address( $from_address, $WC_Email ) {
|
||||
return $this->options->getMessageSenderEmail();
|
||||
}
|
||||
|
||||
public function overide_email_settings( $settings ) {
|
||||
|
||||
$key = $this->find_woocommerce_email_from_address( $settings );
|
||||
|
||||
if ( $key ) {
|
||||
$settings[$key] = array(
|
||||
'title' => __( '"From" address', 'post-smtp' ),
|
||||
'desc' => __( 'This is override by the account configured on Post SMTP plugin configuration.', 'post-smtp' ),
|
||||
'id' => 'woocommerce_email_from_address',
|
||||
'type' => 'email',
|
||||
'custom_attributes' => array(
|
||||
'multiple' => 'multiple',
|
||||
'disabled' => 'true',
|
||||
),
|
||||
'css' => 'min-width:300px;',
|
||||
'default' => $this->options->getMessageSenderEmail(),
|
||||
'autoload' => false,
|
||||
'desc_tip' => true,
|
||||
);
|
||||
}
|
||||
|
||||
return $settings;
|
||||
}
|
||||
|
||||
private function find_woocommerce_email_from_address($settings) {
|
||||
foreach ( $settings as $key => $data ) {
|
||||
if ( isset( $data['id'] ) && $data['id'] == 'woocommerce_email_from_address' ) {
|
||||
return $key;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,288 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'PostmanZendMailEngine' ) ) {
|
||||
|
||||
require_once 'Zend-1.12.10/Loader.php';
|
||||
require_once 'Zend-1.12.10/Registry.php';
|
||||
require_once 'Zend-1.12.10/Mime/Message.php';
|
||||
require_once 'Zend-1.12.10/Mime/Part.php';
|
||||
require_once 'Zend-1.12.10/Mime.php';
|
||||
require_once 'Zend-1.12.10/Validate/Interface.php';
|
||||
require_once 'Zend-1.12.10/Validate/Abstract.php';
|
||||
require_once 'Zend-1.12.10/Validate.php';
|
||||
require_once 'Zend-1.12.10/Validate/Ip.php';
|
||||
require_once 'Zend-1.12.10/Validate/Hostname.php';
|
||||
require_once 'Zend-1.12.10/Mail.php';
|
||||
require_once 'Zend-1.12.10/Exception.php';
|
||||
require_once 'Zend-1.12.10/Mail/Exception.php';
|
||||
require_once 'Zend-1.12.10/Mail/Transport/Exception.php';
|
||||
require_once 'Zend-1.12.10/Mail/Transport/Abstract.php';
|
||||
require_once 'Zend-1.12.10/Mail/Transport/Smtp.php';
|
||||
require_once 'Zend-1.12.10/Mail/Transport/Sendmail.php';
|
||||
require_once 'Zend-1.12.10/Mail/Protocol/Abstract.php';
|
||||
require_once 'Zend-1.12.10/Mail/Protocol/Exception.php';
|
||||
require_once 'Zend-1.12.10/Mail/Protocol/Smtp.php';
|
||||
require_once 'Zend-1.12.10/Mail/Protocol/Smtp/Auth/Oauth2.php';
|
||||
require_once 'Zend-1.12.10/Mail/Protocol/Smtp/Auth/Login.php';
|
||||
require_once 'Zend-1.12.10/Mail/Protocol/Smtp/Auth/Crammd5.php';
|
||||
require_once 'Zend-1.12.10/Mail/Protocol/Smtp/Auth/Plain.php';
|
||||
|
||||
/**
|
||||
* This class knows how to interface with Wordpress
|
||||
* including loading/saving to the database.
|
||||
*
|
||||
* The various Transports available:
|
||||
* http://framework.zend.com/manual/current/en/modules/zend.mail.smtp.options.html
|
||||
*
|
||||
* @author jasonhendriks
|
||||
*/
|
||||
class PostmanZendMailEngine implements PostmanMailEngine {
|
||||
|
||||
// logger for all concrete classes - populate with setLogger($logger)
|
||||
protected $logger;
|
||||
|
||||
// the result
|
||||
private $transcript;
|
||||
|
||||
private $transport;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param mixed $senderEmail
|
||||
* @param mixed $accessToken
|
||||
*/
|
||||
function __construct( PostmanZendModuleTransport $transport ) {
|
||||
assert( isset( $transport ) );
|
||||
$this->transport = $transport;
|
||||
|
||||
// create the logger
|
||||
$this->logger = new PostmanLogger( get_class( $this ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* (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/post-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' );
|
||||
|
||||
$sender = $this->transport->getFromEmailAddress();
|
||||
|
||||
/**
|
||||
* If Sender and From are not same thn ADD Sender, otherwise do not add Sender
|
||||
* From RFC 2822 Section 3.6.2: https://www.rfc-editor.org/rfc/rfc2822#section-3.6.2
|
||||
*
|
||||
* @since 2.3.0
|
||||
*/
|
||||
if( !$this->is_from_and_sender_same( $message, $sender ) ) {
|
||||
|
||||
// add the Sender Header, overriding what the user may have set
|
||||
$mail->addHeader( 'Sender', $sender, 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() );
|
||||
}
|
||||
|
||||
// add the message content
|
||||
{
|
||||
$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() );
|
||||
|
||||
$transport = $this->transport instanceof PostmanDefaultModuleTransport ? null : $zendTransport;
|
||||
|
||||
try {
|
||||
// send the message
|
||||
$this->logger->debug( 'Sending mail' );
|
||||
$mail->send( $transport );
|
||||
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.', 'post-smtp' ) );
|
||||
}
|
||||
// create a new exception
|
||||
$newException = new Exception( $message, $e->getCode() );
|
||||
// throw the new exception after handling
|
||||
throw $newException;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the sender from PostmanMessage and add it to the Postman_Zend_Mail object
|
||||
*
|
||||
* @param PostmanMessage $message
|
||||
* @param Postman_Zend_Mail $mail
|
||||
* @return PostmanEmailAddress
|
||||
*/
|
||||
public function addFrom( PostmanMessage $message, Postman_Zend_Mail $mail ) {
|
||||
$sender = $message->getFromAddress();
|
||||
// now log it and push it into the message
|
||||
$senderEmail = $sender->getEmail();
|
||||
$senderName = $sender->getName();
|
||||
assert( ! empty( $senderEmail ) );
|
||||
if ( ! empty( $senderName ) ) {
|
||||
$mail->setFrom( $senderEmail, $senderName );
|
||||
} else {
|
||||
$mail->setFrom( $senderEmail );
|
||||
}
|
||||
return $sender;
|
||||
}
|
||||
|
||||
// return the SMTP session transcript
|
||||
public function getTranscript() {
|
||||
return $this->transcript;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check Whather, From And Sender Are Same
|
||||
*
|
||||
* @param PostmanMessage $message
|
||||
* @param String $sender
|
||||
* @since 2.3.0
|
||||
* @version 1.0.0
|
||||
*/
|
||||
public function is_from_and_sender_same( PostmanMessage $message, $sender = '' ) {
|
||||
|
||||
$sender = empty( $sender ) ? $this->transport->getEnvelopeFromEmailAddress() : $sender;
|
||||
$from = $message->getFromAddress();
|
||||
$from_email = $from->getEmail();
|
||||
|
||||
if( $sender == $from_email ) {
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
if (! interface_exists ( 'PostmanZendMailTransportConfigurationFactory' )) {
|
||||
interface PostmanZendMailTransportConfigurationFactory {
|
||||
static function createConfig(PostmanTransport $transport);
|
||||
}
|
||||
}
|
||||
|
||||
if (! class_exists ( 'PostmanBasicAuthConfigurationFactory' )) {
|
||||
class PostmanBasicAuthConfigurationFactory implements PostmanZendMailTransportConfigurationFactory {
|
||||
public static function createConfig(PostmanTransport $transport) {
|
||||
|
||||
// create Logger
|
||||
$logger = new PostmanLogger ( "PostmanBasicAuthConfigurationFactory" );
|
||||
|
||||
// retrieve the hostname and port form the transport
|
||||
$hostname = $transport->getHostname ();
|
||||
$port = $transport->getPort ();
|
||||
$securityType = $transport->getSecurityType ();
|
||||
$authType = $transport->getAuthenticationType ();
|
||||
$username = $transport->getCredentialsId ();
|
||||
$password = $transport->getCredentialsSecret ();
|
||||
|
||||
// create the Configuration structure for Zend_Mail
|
||||
$config = array (
|
||||
'port' => $port
|
||||
);
|
||||
$logger->debug ( sprintf ( 'Using %s:%s ', $hostname, $port ) );
|
||||
if ($securityType != PostmanOptions::SECURITY_TYPE_NONE) {
|
||||
$config ['ssl'] = $securityType;
|
||||
$logger->debug ( 'Using encryption ' . $securityType );
|
||||
} else {
|
||||
$logger->debug ( 'Using no encryption' );
|
||||
}
|
||||
if ($authType != PostmanOptions::AUTHENTICATION_TYPE_NONE) {
|
||||
$config ['auth'] = $authType;
|
||||
$config ['username'] = $username;
|
||||
$config ['password'] = $password;
|
||||
$logger->debug ( sprintf ( 'Using auth %s with username %s and password %s', $authType, $username, PostmanUtils::obfuscatePassword ( $password ) ) );
|
||||
} else {
|
||||
$logger->debug ( 'Using no authentication' );
|
||||
}
|
||||
|
||||
// return the Configuration structure
|
||||
return $config;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! class_exists ( 'PostmanOAuth2ConfigurationFactory' )) {
|
||||
class PostmanOAuth2ConfigurationFactory implements PostmanZendMailTransportConfigurationFactory {
|
||||
public static function createConfig(PostmanTransport $transport) {
|
||||
|
||||
// create Logger
|
||||
$logger = new PostmanLogger ( 'PostmanOAuth2ConfigurationFactory' );
|
||||
|
||||
// retrieve the hostname and port form the transport
|
||||
$hostname = $transport->getHostname ();
|
||||
$port = $transport->getPort ();
|
||||
|
||||
// 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 = self::createVendorString ( $hostname );
|
||||
|
||||
// create the OAuth2 SMTP Authentication string
|
||||
$initClientRequestEncoded = self::createAuthenticationString ( $senderEmail, PostmanOAuthToken::getInstance ()->getAccessToken (), $vendor );
|
||||
|
||||
// create the Configuration structure for Zend_Mail
|
||||
$config = self::createConfiguration ( $logger, $hostname, $port, $transport->getSecurityType (), $transport->getAuthenticationType (), $initClientRequestEncoded );
|
||||
|
||||
// return the Configuration structure
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Create the Configuration structure for Zend_Mail
|
||||
*
|
||||
* @param mixed $hostname
|
||||
* @param mixed $port
|
||||
* @param mixed $securityType
|
||||
* @param mixed $authenticationType
|
||||
* @param mixed $initClientRequestEncoded
|
||||
* @return multitype:unknown NULL
|
||||
*/
|
||||
private static function createConfiguration($logger, $hostname, $port, $securityType, $authenticationType, $initClientRequestEncoded) {
|
||||
$config = array (
|
||||
'ssl' => $securityType,
|
||||
'port' => $port,
|
||||
'auth' => $authenticationType,
|
||||
'xoauth2_request' => $initClientRequestEncoded
|
||||
);
|
||||
$logger->debug ( sprintf ( 'Using auth %s with encryption %s to %s:%s ', $config ['auth'], $config ['ssl'], $hostname, $config ['port'] ) );
|
||||
return $config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the vendor string (for Yahoo servers only)
|
||||
*
|
||||
* @param mixed $hostname
|
||||
* @return string
|
||||
*/
|
||||
private static function createVendorString($hostname) {
|
||||
// the vendor is required for Yahoo's OAuth2 implementation
|
||||
$vendor = '';
|
||||
if (PostmanUtils::endsWith ( $hostname, 'yahoo.com' )) {
|
||||
// Yahoo Mail requires a Vendor - see http://imapclient.freshfoo.com/changeset/535%3A80ae438f4e4a/
|
||||
$pluginData = apply_filters ( 'postman_get_plugin_metadata', null );
|
||||
$vendor = sprintf ( "vendor=Postman SMTP %s\1", $pluginData ['version'] );
|
||||
}
|
||||
return $vendor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the standard OAuth2 SMTP Authentication string
|
||||
*
|
||||
* @param mixed $senderEmail
|
||||
* @param mixed $oauth2AccessToken
|
||||
* @param mixed $vendor
|
||||
* @return string
|
||||
*/
|
||||
private static function createAuthenticationString($senderEmail, $oauth2AccessToken, $vendor) {
|
||||
$initClientRequestEncoded = base64_encode ( sprintf ( "user=%s\1auth=Bearer %s\1%s\1", $senderEmail, $oauth2AccessToken, $vendor ) );
|
||||
return $initClientRequestEncoded;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
class PostmanElasticEmail extends PostmanServiceRequest {
|
||||
|
||||
/**
|
||||
* Success Code
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @version 1.0
|
||||
*/
|
||||
private $email_sent_code = 200;
|
||||
|
||||
/**
|
||||
* API Key
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @version 1.0
|
||||
*/
|
||||
private $api_key = '';
|
||||
|
||||
/**
|
||||
* Base URL
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @version 1.0
|
||||
*/
|
||||
private $base_url = 'https://api.elasticemail.com/v4/emails';
|
||||
|
||||
/**
|
||||
* constructor ElasticEmail
|
||||
*
|
||||
* @param $api_key
|
||||
* @since 2.6.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function __construct( $api_key ) {
|
||||
|
||||
$this->api_key = $api_key;
|
||||
|
||||
parent::__construct( $this->base_url );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares Header for Request
|
||||
*
|
||||
* @since 2.6.0
|
||||
* @version 1.0
|
||||
*/
|
||||
private function get_headers() {
|
||||
|
||||
return array(
|
||||
'X-ElasticEmail-ApiKey' => $this->api_key
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends Email using ElasticEmail transactional end point
|
||||
*
|
||||
* @param $api_key
|
||||
* @since 2.6.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function send( $content ) {
|
||||
|
||||
$content = json_encode( $content );
|
||||
|
||||
return $this->request(
|
||||
'POST',
|
||||
'/transactional',
|
||||
$this->get_headers(),
|
||||
$content,
|
||||
$this->email_sent_code
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
class PostmanEmailit extends PostmanServiceRequest {
|
||||
/**
|
||||
* Success Code
|
||||
*/
|
||||
private $email_sent_code = 200;
|
||||
|
||||
/**
|
||||
* API Key
|
||||
*/
|
||||
private $api_key = '';
|
||||
|
||||
/**
|
||||
* Base URL (endpoint)
|
||||
*/
|
||||
private $base_url = 'https://api.emailit.com';
|
||||
|
||||
/**
|
||||
* Options instance
|
||||
* @var PostmanOptions
|
||||
*/
|
||||
private $options;
|
||||
|
||||
/**
|
||||
* constructor PostmanEmailit
|
||||
* @param $api_key
|
||||
* @param $endpoint
|
||||
*/
|
||||
public function __construct( $api_key ) {
|
||||
$this->api_key = $api_key;
|
||||
parent::__construct( $this->base_url );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares Header for Request
|
||||
*/
|
||||
private function get_headers() {
|
||||
return array(
|
||||
'Content-Type' => 'application/json',
|
||||
'Authorization' => 'Bearer ' . $this->api_key
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends Email using Emailit API
|
||||
* @param $content
|
||||
* @return mixed
|
||||
*/
|
||||
public function send( $content ) {
|
||||
$content = json_encode( $content );
|
||||
return $this->request(
|
||||
'POST',
|
||||
'/v1/emails',
|
||||
$this->get_headers(),
|
||||
$content,
|
||||
$this->email_sent_code
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
<?php
|
||||
|
||||
class PostmanMailGun extends PostmanServiceRequest {
|
||||
|
||||
/**
|
||||
* Success Code
|
||||
*
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
private $email_sent_code = 200;
|
||||
|
||||
/**
|
||||
* API Key
|
||||
*
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
private $api_key = '';
|
||||
|
||||
/**
|
||||
* Base URL US Region
|
||||
*
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
private $base_url_us = 'https://api.mailgun.net/v3/';
|
||||
/**
|
||||
* Base URL EU Region
|
||||
*
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
private $base_url_eu = 'https://api.eu.mailgun.net/v3/';
|
||||
|
||||
/**
|
||||
* Content
|
||||
*
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
private $content = array();
|
||||
|
||||
/**
|
||||
* constructor PostmanMailGun
|
||||
*
|
||||
* @param $api_key
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function __construct( $api_key, $region, $domain ) {
|
||||
$base_url = ! is_null( $region ) ? $this->base_url_eu : $this->base_url_us;
|
||||
$base_url .= $domain;
|
||||
|
||||
$this->api_key = $api_key;
|
||||
parent::__construct( $base_url );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares Header for Request
|
||||
*
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
private function get_headers() {
|
||||
|
||||
$headers = array();
|
||||
$headers['Authorization'] = 'Basic ' . base64_encode('api:' . $this->api_key);
|
||||
|
||||
|
||||
if( isset( $this->content['attachment'] ) ) {
|
||||
|
||||
//Remove attachment from content, to manage it separately
|
||||
$attachments = $this->content['attachment'];
|
||||
unset( $this->content['attachment'] );
|
||||
|
||||
//Let's create the boundary string. It must be unique
|
||||
//so we use the MD5 algorithm to generate a random hash
|
||||
$boundary = md5( date( 'r', time() ) );
|
||||
$headers['Content-Type'] = 'multipart/form-data; boundary=' . $boundary;
|
||||
$payload = '';
|
||||
|
||||
foreach( $this->content as $key => $value ) {
|
||||
|
||||
if ( is_array( $value ) ) {
|
||||
|
||||
foreach ( $value as $child_value ) {
|
||||
|
||||
$payload .= '--' . $boundary;
|
||||
$payload .= "\r\n";
|
||||
$payload .= 'Content-Disposition: form-data; name="' . $key . "\"\r\n\r\n";
|
||||
$payload .= $child_value;
|
||||
$payload .= "\r\n";
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
$payload .= '--' . $boundary;
|
||||
$payload .= "\r\n";
|
||||
$payload .= 'Content-Disposition: form-data; name="' . $key . '"' . "\r\n\r\n";
|
||||
$payload .= $value;
|
||||
$payload .= "\r\n";
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//Add attachments
|
||||
foreach( $attachments as $key => $attachment ) {
|
||||
|
||||
$payload .= '--' . $boundary;
|
||||
$payload .= "\r\n";
|
||||
$payload .= 'Content-Disposition: form-data; name="attachment[' . $key . ']"; filename="' . $attachment['filePath'] . '"' . "\r\n\r\n";
|
||||
$payload .= file_get_contents( $attachment['filePath'] );
|
||||
$payload .= "\r\n";
|
||||
|
||||
}
|
||||
|
||||
$payload .= '--' . $boundary . '--';
|
||||
|
||||
//Overwrite body with payload
|
||||
$this->content = $payload;
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
$headers['Content-Type'] = 'application/x-www-form-urlencoded';
|
||||
|
||||
}
|
||||
|
||||
return $headers;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends Email using MailGun email end point
|
||||
*
|
||||
* @param $api_key
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function send( $content ) {
|
||||
|
||||
$this->content = $content;
|
||||
|
||||
return $this->request(
|
||||
'POST',
|
||||
'/messages',
|
||||
$this->get_headers(),
|
||||
$this->content,
|
||||
$this->email_sent_code
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
class PostmanMailerSend extends PostmanServiceRequest {
|
||||
|
||||
/**
|
||||
* Success Code
|
||||
*
|
||||
* @since 3.3.0
|
||||
* @version 1.0
|
||||
*/
|
||||
private $email_sent_code = 202;
|
||||
|
||||
/**
|
||||
* API Key
|
||||
*
|
||||
* @since 3.3.0
|
||||
* @version 1.0
|
||||
*/
|
||||
private $api_key = '';
|
||||
|
||||
/**
|
||||
* Base URL
|
||||
*
|
||||
* @since 3.3.0
|
||||
* @version 1.0
|
||||
*/
|
||||
private $base_url = 'https://api.mailersend.com/v1/';
|
||||
|
||||
/**
|
||||
* Options instance
|
||||
*
|
||||
* @var PostmanOptions
|
||||
*/
|
||||
private $options;
|
||||
|
||||
/**
|
||||
* constructor PostmanMailerSend
|
||||
*
|
||||
* @param $api_key
|
||||
* @since 3.3.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function __construct( $api_key ) {
|
||||
|
||||
$this->api_key = $api_key;
|
||||
$this->options = PostmanOptions::getInstance();
|
||||
parent::__construct( $this->base_url );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares Header for Request
|
||||
*
|
||||
* @since 3.3.0
|
||||
* @version 1.0
|
||||
*/
|
||||
private function get_headers() {
|
||||
|
||||
return array(
|
||||
'Content-Type' => 'application/json',
|
||||
'Authorization' => 'Bearer ' . $this->api_key
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends Email using MailerSend email end point
|
||||
*
|
||||
* @param $api_key
|
||||
* @since 3.3.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function send( $content ) {
|
||||
|
||||
$content = json_encode( $content );
|
||||
|
||||
return $this->request(
|
||||
'POST',
|
||||
'email',
|
||||
$this->get_headers(),
|
||||
$content,
|
||||
$this->email_sent_code
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
class PostmanMaileroo extends PostmanServiceRequest {
|
||||
/**
|
||||
* Success Code
|
||||
*/
|
||||
private $email_sent_code = 200;
|
||||
|
||||
/**
|
||||
* API Key
|
||||
*/
|
||||
private $api_key = '';
|
||||
|
||||
/**
|
||||
* Base URL (endpoint)
|
||||
*/
|
||||
private $base_url = 'https://smtp.maileroo.com/';
|
||||
|
||||
/**
|
||||
* Options instance
|
||||
* @var PostmanOptions
|
||||
*/
|
||||
private $options;
|
||||
|
||||
/**
|
||||
* constructor PostmanMaileroo
|
||||
* @param $api_key
|
||||
* @param $endpoint
|
||||
*/
|
||||
public function __construct( $api_key ) {
|
||||
$this->api_key = $api_key;
|
||||
parent::__construct( $this->base_url );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares Header for Request
|
||||
*/
|
||||
private function get_headers() {
|
||||
return array(
|
||||
'Content-Type' => 'application/json',
|
||||
'Authorization' => 'Bearer ' . $this->api_key
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends Email using Maileroo API
|
||||
* @param $content
|
||||
* @return mixed
|
||||
*/
|
||||
public function send( $content ) {
|
||||
$content = json_encode( $content );
|
||||
return $this->request(
|
||||
'POST',
|
||||
'api/v2/emails',
|
||||
$this->get_headers(),
|
||||
$content,
|
||||
$this->email_sent_code
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
class PostmanMailjet extends PostmanServiceRequest {
|
||||
|
||||
/**
|
||||
* Success Code
|
||||
*
|
||||
* @since 2.7
|
||||
* @version 1.0
|
||||
*/
|
||||
private $email_sent_code = 200;
|
||||
|
||||
/**
|
||||
* API Key
|
||||
*
|
||||
* @since 2.7
|
||||
* @version 1.0
|
||||
*/
|
||||
private $api_key = '';
|
||||
private $secret_key = '';
|
||||
private $auth = false;
|
||||
|
||||
|
||||
/**
|
||||
* Base URL
|
||||
*
|
||||
* @since 2.7
|
||||
* @version 1.0
|
||||
*/
|
||||
private $base_url = 'https://api.mailjet.com/v3';
|
||||
|
||||
/**
|
||||
* constructor PostmanMailjet
|
||||
*
|
||||
* @param $api_key
|
||||
* @since 2.7
|
||||
* @version 1.0
|
||||
*/
|
||||
public function __construct( $api_key, $secret_key ) {
|
||||
|
||||
$this->api_key = $api_key;
|
||||
$this->secret_key =$secret_key;
|
||||
|
||||
parent::__construct( $this->base_url );
|
||||
|
||||
}
|
||||
|
||||
private function get_auth(){
|
||||
|
||||
if( isset( $this->api_key ) && isset( $this->secret_key ) ) {
|
||||
|
||||
$this->auth = base64_encode( "{$this->api_key}:{$this->secret_key}" );
|
||||
|
||||
}
|
||||
|
||||
return $this->auth;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prepares Header for Request
|
||||
*
|
||||
* @since 2.7
|
||||
* @version 1.0
|
||||
*/
|
||||
private function get_headers() {
|
||||
|
||||
$auth = $this->get_auth();
|
||||
|
||||
return array(
|
||||
'Authorization' => "Basic {$auth}",
|
||||
'Content-Type' => 'application/json'
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends Email using Mailjet transmissions end point
|
||||
*
|
||||
* @since 2.7
|
||||
* @version 1.0
|
||||
*/
|
||||
public function send( $content ) {
|
||||
|
||||
$content = json_encode( $content );
|
||||
|
||||
return $this->request(
|
||||
'POST',
|
||||
'/send',
|
||||
$this->get_headers(),
|
||||
$content,
|
||||
$this->email_sent_code
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
|
||||
class PostmanMailtrap extends PostmanServiceRequest {
|
||||
|
||||
/**
|
||||
* Success Code
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
private $email_sent_code = 200;
|
||||
|
||||
/**
|
||||
* API Key
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
private $api_key = '';
|
||||
|
||||
/**
|
||||
* Base URL
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
private $base_url = 'https://send.api.mailtrap.io/api';
|
||||
|
||||
/**
|
||||
* constructor PostmanMailtrap
|
||||
*
|
||||
* @param $api_key
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function __construct( $api_key ) {
|
||||
|
||||
$this->api_key = $api_key;
|
||||
|
||||
parent::__construct( $this->base_url );
|
||||
|
||||
// Set timeout for API requests
|
||||
$this->set_additional_args( array(
|
||||
'timeout' => 30
|
||||
) );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares Header for Request
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
private function get_headers() {
|
||||
|
||||
return array(
|
||||
'Api-Token' => $this->api_key,
|
||||
'Content-Type' => 'application/json',
|
||||
'Accept' => 'application/json'
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends Email using Mailtrap send endpoint
|
||||
*
|
||||
* @param array $content
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function send( $content ) {
|
||||
|
||||
$content = json_encode( $content );
|
||||
|
||||
if ( $content === false ) {
|
||||
throw new Exception( 'Failed to encode email content to JSON' );
|
||||
}
|
||||
|
||||
return $this->request(
|
||||
'POST',
|
||||
'/send',
|
||||
$this->get_headers(),
|
||||
$content,
|
||||
$this->email_sent_code
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
class PostmanMandrill extends PostmanServiceRequest {
|
||||
|
||||
/**
|
||||
* Success Code
|
||||
*
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
private $email_sent_code = 200;
|
||||
|
||||
/**
|
||||
* API Key
|
||||
*
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
private $api_key = '';
|
||||
|
||||
/**
|
||||
* Base URL
|
||||
*
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
private $base_url = 'https://mandrillapp.com/api/1.0';
|
||||
|
||||
/**
|
||||
* constructor PostmanMandril
|
||||
*
|
||||
* @param $api_key
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function __construct( $api_key ) {
|
||||
|
||||
$this->api_key = $api_key;
|
||||
|
||||
parent::__construct( $this->base_url );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares Header for Request
|
||||
*
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
private function get_headers() {
|
||||
|
||||
return array(
|
||||
'Content-Type' => 'application/json',
|
||||
'Accept' => 'application/json',
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends Email using PostMark email end point
|
||||
*
|
||||
* @param $api_key
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function send( $content ) {
|
||||
$content = json_encode( $content );
|
||||
|
||||
return $this->request(
|
||||
'POST',
|
||||
'/messages/send.json',
|
||||
$this->get_headers(),
|
||||
$content,
|
||||
$this->email_sent_code
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
|
||||
class PostmanPostMark extends PostmanServiceRequest {
|
||||
|
||||
/**
|
||||
* Success Code
|
||||
*
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
private $email_sent_code = 200;
|
||||
|
||||
/**
|
||||
* API Key
|
||||
*
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
private $api_key = '';
|
||||
|
||||
/**
|
||||
* Base URL
|
||||
*
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
private $base_url = 'https://api.postmarkapp.com';
|
||||
|
||||
/**
|
||||
* constructor PostmanPostMark
|
||||
*
|
||||
* @param $api_key
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function __construct( $api_key ) {
|
||||
|
||||
$this->api_key = $api_key;
|
||||
|
||||
parent::__construct( $this->base_url );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares Header for Request
|
||||
*
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
private function get_headers() {
|
||||
|
||||
return array(
|
||||
'X-Postmark-Server-Token' => $this->api_key,
|
||||
'Content-Type' => 'application/json',
|
||||
'Accept' => 'application/json',
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends Email using PostMark email end point
|
||||
*
|
||||
* @param $api_key
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function send( $content ) {
|
||||
|
||||
/**
|
||||
* Filters the content before sending
|
||||
*
|
||||
* @since 2.9.2
|
||||
*/
|
||||
$content = json_encode( apply_filters( 'post_smtp_postmark_content' , $content ) );
|
||||
|
||||
return $this->request(
|
||||
'POST',
|
||||
'/email',
|
||||
$this->get_headers(),
|
||||
$content,
|
||||
$this->email_sent_code
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
<?php
|
||||
|
||||
class PostmanServiceRequest {
|
||||
|
||||
|
||||
/**
|
||||
* Base URL
|
||||
*
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
private $base_url = '';
|
||||
|
||||
/**
|
||||
* Additional Args
|
||||
*
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
private $additional_args = array();
|
||||
|
||||
/**
|
||||
* Request Response
|
||||
*
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
private $response = array();
|
||||
|
||||
/**
|
||||
* constructor PostmanServiceRequest
|
||||
*
|
||||
* @param $base_url
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function __construct( $base_url ) {
|
||||
|
||||
$this->base_url = $base_url;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Additional Args
|
||||
*
|
||||
* @param $args
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function set_additional_args( $args ) {
|
||||
|
||||
$this->additional_args = $args;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes Remote Request
|
||||
*
|
||||
* @param $method
|
||||
* @param $end_point
|
||||
* @param $headers
|
||||
* @param $body
|
||||
* @param $success_code
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function request( $method, $end_point, $headers = array(), $body = array(), $success_code = 200 ) {
|
||||
|
||||
$url = "{$this->base_url}{$end_point}";
|
||||
$args = array(
|
||||
'method' => $method,
|
||||
'headers' => $headers,
|
||||
'body' => $body
|
||||
);
|
||||
|
||||
//Set Additional Args (If Set)
|
||||
if( !empty( $this->additional_args ) ) {
|
||||
|
||||
$args = array_merge( $this->additional_args, $args );
|
||||
|
||||
}
|
||||
|
||||
$this->response = wp_remote_post(
|
||||
$url,
|
||||
$args
|
||||
);
|
||||
|
||||
$response_code = $this->get_response_code();
|
||||
|
||||
if( $response_code == $success_code ) {
|
||||
|
||||
return $this->response;
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
$this->exception();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets Reponse Code
|
||||
*
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function get_response_code() {
|
||||
|
||||
return wp_remote_retrieve_response_code( $this->response );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets Response message
|
||||
*
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function get_response_message() {
|
||||
|
||||
return wp_remote_retrieve_response_message( $this->response );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets Response Body
|
||||
*
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function get_response_body() {
|
||||
|
||||
return wp_remote_retrieve_body( $this->response );
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create and throw Exception
|
||||
*
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function exception() {
|
||||
|
||||
$message = "Code: {$this->get_response_code()}, Message: {$this->get_response_message()}, Body: {$this->get_response_body()}";
|
||||
|
||||
throw new Exception( $message );
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
class PostmanResend extends PostmanServiceRequest {
|
||||
|
||||
/**
|
||||
* Success Code
|
||||
*
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
private $email_sent_code = 200;
|
||||
|
||||
/**
|
||||
* API Key
|
||||
*
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
private $api_key = '';
|
||||
|
||||
/**
|
||||
* Base URL
|
||||
*
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
private $base_url = 'https://api.resend.com';
|
||||
|
||||
/**
|
||||
* constructor PostmanResend
|
||||
*
|
||||
* @param $api_key
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function __construct( $api_key ) {
|
||||
|
||||
$this->api_key = $api_key;
|
||||
|
||||
parent::__construct( $this->base_url );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares Header for Request
|
||||
*
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
private function get_headers() {
|
||||
|
||||
return array(
|
||||
'Authorization' => 'Bearer ' . $this->api_key,
|
||||
'Content-Type' => 'application/json'
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends Email using Resend emails endpoint
|
||||
*
|
||||
* @param $content
|
||||
* @since 3.2.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function send( $content ) {
|
||||
|
||||
$content = json_encode( $content );
|
||||
|
||||
return $this->request(
|
||||
'POST',
|
||||
'/emails',
|
||||
$this->get_headers(),
|
||||
$content,
|
||||
$this->email_sent_code
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
class PostmanSendGrid extends PostmanServiceRequest {
|
||||
|
||||
/**
|
||||
* Success Code
|
||||
*
|
||||
* @since 2.4
|
||||
* @version 1.0
|
||||
*/
|
||||
private $email_sent_code = 202;
|
||||
|
||||
/**
|
||||
* API Key
|
||||
*
|
||||
* @since 2.4
|
||||
* @version 1.0
|
||||
*/
|
||||
private $api_key = '';
|
||||
|
||||
/**
|
||||
* Base URL
|
||||
*
|
||||
* @since 2.4
|
||||
* @version 1.0
|
||||
*/
|
||||
private $base_url = 'https://api.sendgrid.com/v3/mail';
|
||||
|
||||
/**
|
||||
* Options instance
|
||||
*
|
||||
* @var PostmanOptions
|
||||
*/
|
||||
private $options;
|
||||
|
||||
/**
|
||||
* constructor PostmanSendGrid
|
||||
*
|
||||
* @param $api_key
|
||||
* @since 2.4
|
||||
* @version 1.0
|
||||
*/
|
||||
public function __construct( $api_key ) {
|
||||
|
||||
$this->api_key = $api_key;
|
||||
$this->options = PostmanOptions::getInstance();
|
||||
$region = $this->options->getSendGridRegion();
|
||||
|
||||
if ( 'EU' === $region || apply_filters( 'post_smtp_enable_sendgrid_eu', false ) ) {
|
||||
$this->base_url = 'https://api.eu.sendgrid.com/v3/mail';
|
||||
}
|
||||
|
||||
$this->base_url = apply_filters( 'post_smtp_sendgrid_base_url', $this->base_url, $region );
|
||||
parent::__construct( $this->base_url );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares Header for Request
|
||||
*
|
||||
* @since 2.4
|
||||
* @version 1.0
|
||||
*/
|
||||
private function get_headers() {
|
||||
|
||||
return array(
|
||||
'Content-Type' => 'application/json',
|
||||
'Authorization' => 'Bearer ' . $this->api_key
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends Email using SendGrid email end point
|
||||
*
|
||||
* @param $api_key
|
||||
* @since 2.4
|
||||
* @version 1.0
|
||||
*/
|
||||
public function send( $content ) {
|
||||
|
||||
$content = json_encode( $content );
|
||||
|
||||
return $this->request(
|
||||
'POST',
|
||||
'/send',
|
||||
$this->get_headers(),
|
||||
$content,
|
||||
$this->email_sent_code
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
<?php
|
||||
|
||||
class PostmanSendpulse extends PostmanServiceRequest {
|
||||
|
||||
/**
|
||||
* Success Code
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
private $email_sent_code = 200;
|
||||
|
||||
/**
|
||||
* API Key and Secret Key
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
private $api_key = ' ';
|
||||
private $secret_key = ' ';
|
||||
|
||||
|
||||
/**
|
||||
* Parameters used to get Token
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
private $grant_type = 'client_credentials';
|
||||
private $auth_response_body = ' ';
|
||||
private $auth_response = ' ';
|
||||
private $token = ' ';
|
||||
|
||||
/**
|
||||
* Base URL
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
private $base_url = 'https://api.sendpulse.com';
|
||||
|
||||
|
||||
/**
|
||||
* Constructor PostmanSendpulse
|
||||
*
|
||||
* @param mixed $api_key Api Key.
|
||||
* @param mixed $secret_key Secret Key.
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function __construct( $api_key, $secret_key )
|
||||
{
|
||||
|
||||
$this->api_key = $api_key;
|
||||
$this->secret_key = $secret_key;
|
||||
parent::__construct( $this->base_url );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Header to get token
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
private function auth_headers() {
|
||||
|
||||
return array(
|
||||
'Content-Type' => 'application/json'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Body to get token
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
private function auth_body() {
|
||||
|
||||
return array(
|
||||
'grant_type' => $this->grant_type,
|
||||
'client_id' => $this->api_key,
|
||||
'client_secret' => $this->secret_key
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenciation to get Token
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
private function authentication() {
|
||||
|
||||
$content = json_encode( $this->auth_body() );
|
||||
|
||||
$this->auth_response_body = $this->request(
|
||||
'POST',
|
||||
'/oauth/access_token',
|
||||
$this->auth_headers(),
|
||||
$content,
|
||||
$this->email_sent_code
|
||||
|
||||
);
|
||||
|
||||
$this->auth_response = json_decode( $this->auth_response_body['body'], true );
|
||||
|
||||
//Auto delete token when token expires after given time period.
|
||||
|
||||
set_transient( 'sendpulse_token', $this->auth_response['access_token'], $this->auth_response['expires_in'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares Header for Request
|
||||
*
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
private function get_headers()
|
||||
{
|
||||
|
||||
if ( get_transient('sendpulse_token') ) {
|
||||
|
||||
$this->token = get_transient( 'sendpulse_token' );
|
||||
} else {
|
||||
|
||||
$this->authentication();
|
||||
$this->token = get_transient( 'sendpulse_token' );
|
||||
}
|
||||
|
||||
return array(
|
||||
|
||||
'Content-Type' => 'application/json',
|
||||
'Authorization' => 'Bearer ' . $this->token
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends Email using Sendpulse transmissions end point
|
||||
*
|
||||
* @param mixed $content
|
||||
* @since 2.9.0
|
||||
* @version 1.0
|
||||
*/
|
||||
public function send( $content ) {
|
||||
|
||||
$content = json_encode( $content );
|
||||
|
||||
return $this->request(
|
||||
'POST',
|
||||
'/smtp/emails',
|
||||
$this->get_headers(),
|
||||
$content,
|
||||
$this->email_sent_code
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
class PostmanSendinblue extends PostmanServiceRequest {
|
||||
|
||||
/**
|
||||
* Success Code
|
||||
*
|
||||
* @since 2.3
|
||||
* @version 1.0
|
||||
*/
|
||||
private $email_sent_code = 201;
|
||||
|
||||
/**
|
||||
* API Key
|
||||
*
|
||||
* @since 2.3
|
||||
* @version 1.0
|
||||
*/
|
||||
private $api_key = '';
|
||||
|
||||
/**
|
||||
* Base URL
|
||||
*
|
||||
* @since 2.3
|
||||
* @version 1.0
|
||||
*/
|
||||
private $base_url = 'https://api.brevo.com/v3/smtp';
|
||||
|
||||
/**
|
||||
* constructor PostmanSendinblue
|
||||
*
|
||||
* @param $api_key
|
||||
* @since 2.3
|
||||
* @version 1.0
|
||||
*/
|
||||
public function __construct( $api_key ) {
|
||||
|
||||
$this->api_key = $api_key;
|
||||
|
||||
parent::__construct( $this->base_url );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares Header for Request
|
||||
*
|
||||
* @since 2.3
|
||||
* @version 1.0
|
||||
*/
|
||||
private function get_headers() {
|
||||
|
||||
return array(
|
||||
'Api-Key' => $this->api_key,
|
||||
'Content-Type' => 'application/json',
|
||||
'Accept' => 'application/json'
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends Email using Sendinblue transmissions end point
|
||||
*
|
||||
* @param $api_key
|
||||
* @since 2.3
|
||||
* @version 1.0
|
||||
*/
|
||||
public function send( $content ) {
|
||||
|
||||
$content = json_encode( $content );
|
||||
|
||||
return $this->request(
|
||||
'POST',
|
||||
'/email',
|
||||
$this->get_headers(),
|
||||
$content,
|
||||
$this->email_sent_code
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
/**
|
||||
* PostmanSmtp2GoHandler
|
||||
*
|
||||
* @package Postman
|
||||
*/
|
||||
|
||||
defined( 'ABSPATH' ) || exit;
|
||||
|
||||
if ( ! class_exists( 'PostmanSmtp2GoHandler' ) ) {
|
||||
class PostmanSmtp2GoHandler extends PostmanServiceRequest {
|
||||
private $email_sent_code = 200;
|
||||
private $api_key = '';
|
||||
private $base_url = 'https://api.smtp2go.com/v3/email';
|
||||
|
||||
public function __construct( $api_key ) {
|
||||
$this->api_key = $api_key;
|
||||
|
||||
parent::__construct( $this->base_url );
|
||||
|
||||
// Set 30-second timeout for SMTP2GO requests
|
||||
$this->set_additional_args( array( 'timeout' => 30 ) );
|
||||
}
|
||||
|
||||
private function get_headers() {
|
||||
return array(
|
||||
'Content-Type' => 'application/json',
|
||||
'X-Smtp2go-Api-Key' => $this->api_key,
|
||||
'accept' => 'application/json',
|
||||
);
|
||||
}
|
||||
|
||||
public function send( $content ) {
|
||||
$content = json_encode( $content );
|
||||
|
||||
return $this->request(
|
||||
'POST',
|
||||
'/send',
|
||||
$this->get_headers(),
|
||||
$content,
|
||||
$this->email_sent_code
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
|
||||
class PostmanSparkPost extends PostmanServiceRequest {
|
||||
|
||||
/**
|
||||
* Success Code
|
||||
*
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
private $email_sent_code = 200;
|
||||
|
||||
/**
|
||||
* API Key
|
||||
*
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
private $api_key = '';
|
||||
|
||||
/**
|
||||
* Base URL
|
||||
*
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
private $base_url = 'https://api.sparkpost.com/api/v1';
|
||||
|
||||
/**
|
||||
* Base URL for Global Region
|
||||
*
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
private $base_url_us = 'https://api.sparkpost.com/api/v1';
|
||||
|
||||
/**
|
||||
* Base URL for Europe Region
|
||||
*
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
private $base_url_eu = 'https://api.eu.sparkpost.com/api/v1';
|
||||
|
||||
/**
|
||||
* constructor PostmanSparkPost
|
||||
*
|
||||
* @param $api_key
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function __construct( $api_key ) {
|
||||
|
||||
$this->api_key = $api_key;
|
||||
|
||||
parent::__construct( $this->base_url );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares Header for Request
|
||||
*
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
private function get_headers() {
|
||||
|
||||
return array(
|
||||
'Authorization' => $this->api_key,
|
||||
'Content-Type' => 'application/json'
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends Email using SparkPost transmissions end point
|
||||
*
|
||||
* @param $api_key
|
||||
* @since 2.2
|
||||
* @version 1.0
|
||||
*/
|
||||
public function send( $content ) {
|
||||
|
||||
$content = json_encode( $content );
|
||||
|
||||
return $this->request(
|
||||
'POST',
|
||||
'/transmissions',
|
||||
$this->get_headers(),
|
||||
$content,
|
||||
$this->email_sent_code
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
class PostmanSweego extends PostmanServiceRequest {
|
||||
/**
|
||||
* Success Code
|
||||
*/
|
||||
private $email_sent_code = 200;
|
||||
|
||||
/**
|
||||
* API Key
|
||||
*/
|
||||
private $api_key = '';
|
||||
|
||||
/**
|
||||
* Base URL (endpoint)
|
||||
*/
|
||||
private $base_url = 'https://api.sweego.io';
|
||||
|
||||
/**
|
||||
* Options instance
|
||||
* @var PostmanOptions
|
||||
*/
|
||||
private $options;
|
||||
|
||||
/**
|
||||
* constructor PostmanSweego
|
||||
* @param $api_key
|
||||
* @param $endpoint
|
||||
*/
|
||||
public function __construct( $api_key ) {
|
||||
$this->api_key = $api_key;
|
||||
parent::__construct( $this->base_url );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares Header for Request
|
||||
*/
|
||||
private function get_headers() {
|
||||
return array(
|
||||
'Content-Type' => 'application/json',
|
||||
'Accept' => 'application/json',
|
||||
'Api-Key' => $this->api_key
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends Email using Sweego API
|
||||
* @param $content
|
||||
* @return mixed
|
||||
*/
|
||||
public function send( $content ) {
|
||||
$content = json_encode( $content );
|
||||
return $this->request(
|
||||
'POST',
|
||||
'/send',
|
||||
$this->get_headers(),
|
||||
$content,
|
||||
$this->email_sent_code
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Zend
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Zend
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Postman_Zend_Exception extends Exception
|
||||
{
|
||||
/**
|
||||
* @var null|Exception
|
||||
*/
|
||||
private $_previous = null;
|
||||
|
||||
/**
|
||||
* Construct the exception
|
||||
*
|
||||
* @param string $msg
|
||||
* @param int $code
|
||||
* @param Exception $previous
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($msg = '', $code = 0, ?Exception $previous = null)
|
||||
{
|
||||
if (version_compare(PHP_VERSION, '5.3.0', '<')) {
|
||||
parent::__construct($msg, (int) $code);
|
||||
$this->_previous = $previous;
|
||||
} else {
|
||||
parent::__construct($msg, (int) $code, $previous);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overloading
|
||||
*
|
||||
* For PHP < 5.3.0, provides access to the getPrevious() method.
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $args
|
||||
* @return mixed
|
||||
*/
|
||||
public function __call($method, array $args)
|
||||
{
|
||||
if ('getprevious' == strtolower($method)) {
|
||||
return $this->_getPrevious();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* String representation of the exception
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
if (version_compare(PHP_VERSION, '5.3.0', '<')) {
|
||||
if (null !== ($e = $this->getPrevious())) {
|
||||
return $e->__toString()
|
||||
. "\n\nNext "
|
||||
. parent::__toString();
|
||||
}
|
||||
}
|
||||
return parent::__toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns previous Exception
|
||||
*
|
||||
* @return Exception|null
|
||||
*/
|
||||
protected function _getPrevious()
|
||||
{
|
||||
return $this->_previous;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,343 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Loader
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
/**
|
||||
* Static methods for loading classes and files.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Loader
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Postman_Zend_Loader
|
||||
{
|
||||
/**
|
||||
* Loads a class from a PHP file. The filename must be formatted
|
||||
* as "$class.php".
|
||||
*
|
||||
* If $dirs is a string or an array, it will search the directories
|
||||
* in the order supplied, and attempt to load the first matching file.
|
||||
*
|
||||
* If $dirs is null, it will split the class name at underscores to
|
||||
* generate a path hierarchy (e.g., "Postman_Zend_Example_Class" will map
|
||||
* to "Zend/Example/Class.php").
|
||||
*
|
||||
* If the file was not found in the $dirs, or if no $dirs were specified,
|
||||
* it will attempt to load it from PHP's include_path.
|
||||
*
|
||||
* @param string $class - The full class name of a Zend component.
|
||||
* @param string|array $dirs - OPTIONAL Either a path or an array of paths
|
||||
* to search.
|
||||
* @return void
|
||||
* @throws Postman_Zend_Exception
|
||||
*/
|
||||
public static function loadClass($class, $dirs = null)
|
||||
{
|
||||
if (class_exists($class, false) || interface_exists($class, false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((null !== $dirs) && !is_string($dirs) && !is_array($dirs)) {
|
||||
require_once 'Zend/Exception.php';
|
||||
throw new Postman_Zend_Exception('Directory argument must be a string or an array');
|
||||
}
|
||||
|
||||
$file = self::standardiseFile($class);
|
||||
|
||||
if (!empty($dirs)) {
|
||||
// use the autodiscovered path
|
||||
$dirPath = dirname($file);
|
||||
if (is_string($dirs)) {
|
||||
$dirs = explode(PATH_SEPARATOR, $dirs);
|
||||
}
|
||||
foreach ($dirs as $key => $dir) {
|
||||
if ($dir == '.') {
|
||||
$dirs[$key] = $dirPath;
|
||||
} else {
|
||||
$dir = rtrim($dir, '\\/');
|
||||
$dirs[$key] = $dir . DIRECTORY_SEPARATOR . $dirPath;
|
||||
}
|
||||
}
|
||||
$file = basename($file);
|
||||
self::loadFile($file, $dirs, true);
|
||||
} else {
|
||||
self::loadFile($file, null, true);
|
||||
}
|
||||
|
||||
if (!class_exists($class, false) && !interface_exists($class, false)) {
|
||||
require_once 'Zend/Exception.php';
|
||||
throw new Postman_Zend_Exception("File \"$file\" does not exist or class \"$class\" was not found in the file");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a PHP file. This is a wrapper for PHP's include() function.
|
||||
*
|
||||
* $filename must be the complete filename, including any
|
||||
* extension such as ".php". Note that a security check is performed that
|
||||
* does not permit extended characters in the filename. This method is
|
||||
* intended for loading Zend Framework files.
|
||||
*
|
||||
* If $dirs is a string or an array, it will search the directories
|
||||
* in the order supplied, and attempt to load the first matching file.
|
||||
*
|
||||
* If the file was not found in the $dirs, or if no $dirs were specified,
|
||||
* it will attempt to load it from PHP's include_path.
|
||||
*
|
||||
* If $once is TRUE, it will use include_once() instead of include().
|
||||
*
|
||||
* @param string $filename
|
||||
* @param string|array $dirs - OPTIONAL either a path or array of paths
|
||||
* to search.
|
||||
* @param boolean $once
|
||||
* @return boolean
|
||||
* @throws Postman_Zend_Exception
|
||||
*/
|
||||
public static function loadFile($filename, $dirs = null, $once = false)
|
||||
{
|
||||
self::_securityCheck($filename);
|
||||
|
||||
/**
|
||||
* Search in provided directories, as well as include_path
|
||||
*/
|
||||
$incPath = false;
|
||||
if (!empty($dirs) && (is_array($dirs) || is_string($dirs))) {
|
||||
if (is_array($dirs)) {
|
||||
$dirs = implode(PATH_SEPARATOR, $dirs);
|
||||
}
|
||||
$incPath = get_include_path();
|
||||
set_include_path($dirs . PATH_SEPARATOR . $incPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Try finding for the plain filename in the include_path.
|
||||
*/
|
||||
if ($once) {
|
||||
include_once $filename;
|
||||
} else {
|
||||
include $filename;
|
||||
}
|
||||
|
||||
/**
|
||||
* If searching in directories, reset include_path
|
||||
*/
|
||||
if ($incPath) {
|
||||
set_include_path($incPath);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns TRUE if the $filename is readable, or FALSE otherwise.
|
||||
* This function uses the PHP include_path, where PHP's is_readable()
|
||||
* does not.
|
||||
*
|
||||
* Note from ZF-2900:
|
||||
* If you use custom error handler, please check whether return value
|
||||
* from error_reporting() is zero or not.
|
||||
* At mark of fopen() can not suppress warning if the handler is used.
|
||||
*
|
||||
* @param string $filename
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isReadable($filename)
|
||||
{
|
||||
if (is_readable($filename)) {
|
||||
// Return early if the filename is readable without needing the
|
||||
// include_path
|
||||
return true;
|
||||
}
|
||||
|
||||
if (strtoupper(substr(PHP_OS, 0, 3)) == 'WIN'
|
||||
&& preg_match('/^[a-z]:/i', $filename)
|
||||
) {
|
||||
// If on windows, and path provided is clearly an absolute path,
|
||||
// return false immediately
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (self::explodeIncludePath() as $path) {
|
||||
if ($path == '.') {
|
||||
if (is_readable($filename)) {
|
||||
return true;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
$file = $path . '/' . $filename;
|
||||
if (is_readable($file)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Explode an include path into an array
|
||||
*
|
||||
* If no path provided, uses current include_path. Works around issues that
|
||||
* occur when the path includes stream schemas.
|
||||
*
|
||||
* @param string|null $path
|
||||
* @return array
|
||||
*/
|
||||
public static function explodeIncludePath($path = null)
|
||||
{
|
||||
if (null === $path) {
|
||||
$path = get_include_path();
|
||||
}
|
||||
|
||||
if (PATH_SEPARATOR == ':') {
|
||||
// On *nix systems, include_paths which include paths with a stream
|
||||
// schema cannot be safely explode'd, so we have to be a bit more
|
||||
// intelligent in the approach.
|
||||
$paths = preg_split('#:(?!//)#', $path);
|
||||
} else {
|
||||
$paths = explode(PATH_SEPARATOR, $path);
|
||||
}
|
||||
return $paths;
|
||||
}
|
||||
|
||||
/**
|
||||
* spl_autoload() suitable implementation for supporting class autoloading.
|
||||
*
|
||||
* Attach to spl_autoload() using the following:
|
||||
* <code>
|
||||
* spl_autoload_register(array('Postman_Zend_Loader', 'autoload'));
|
||||
* </code>
|
||||
*
|
||||
* @deprecated Since 1.8.0
|
||||
* @param string $class
|
||||
* @return string|false Class name on success; false on failure
|
||||
*/
|
||||
public static function autoload($class)
|
||||
{
|
||||
trigger_error(__CLASS__ . '::' . __METHOD__ . ' is deprecated as of 1.8.0 and will be removed with 2.0.0; use Postman_Zend_Loader_Autoloader instead', E_USER_NOTICE);
|
||||
try {
|
||||
@self::loadClass($class);
|
||||
return $class;
|
||||
} catch (Exception $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register {@link autoload()} with spl_autoload()
|
||||
*
|
||||
* @deprecated Since 1.8.0
|
||||
* @param string $class (optional)
|
||||
* @param boolean $enabled (optional)
|
||||
* @return void
|
||||
* @throws Postman_Zend_Exception if spl_autoload() is not found
|
||||
* or if the specified class does not have an autoload() method.
|
||||
*/
|
||||
public static function registerAutoload($class = 'Postman_Zend_Loader', $enabled = true)
|
||||
{
|
||||
trigger_error(__CLASS__ . '::' . __METHOD__ . ' is deprecated as of 1.8.0 and will be removed with 2.0.0; use Postman_Zend_Loader_Autoloader instead', E_USER_NOTICE);
|
||||
require_once 'Zend/Loader/Autoloader.php';
|
||||
$autoloader = Postman_Zend_Loader_Autoloader::getInstance();
|
||||
$autoloader->setFallbackAutoloader(true);
|
||||
|
||||
if ('Postman_Zend_Loader' != $class) {
|
||||
self::loadClass($class);
|
||||
$methods = get_class_methods($class);
|
||||
if (!in_array('autoload', (array) $methods)) {
|
||||
require_once 'Zend/Exception.php';
|
||||
throw new Postman_Zend_Exception("The class \"$class\" does not have an autoload() method");
|
||||
}
|
||||
|
||||
$callback = array($class, 'autoload');
|
||||
|
||||
if ($enabled) {
|
||||
$autoloader->pushAutoloader($callback);
|
||||
} else {
|
||||
$autoloader->removeAutoloader($callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that filename does not contain exploits
|
||||
*
|
||||
* @param string $filename
|
||||
* @return void
|
||||
* @throws Postman_Zend_Exception
|
||||
*/
|
||||
protected static function _securityCheck($filename)
|
||||
{
|
||||
/**
|
||||
* Security check
|
||||
*/
|
||||
if (preg_match('/[^a-z0-9\\/\\\\_.:-]/i', $filename)) {
|
||||
require_once 'Zend/Exception.php';
|
||||
throw new Postman_Zend_Exception('Security check: Illegal character in filename');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to include() the file.
|
||||
*
|
||||
* include() is not prefixed with the @ operator because if
|
||||
* the file is loaded and contains a parse error, execution
|
||||
* will halt silently and this is difficult to debug.
|
||||
*
|
||||
* Always set display_errors = Off on production servers!
|
||||
*
|
||||
* @param string $filespec
|
||||
* @param boolean $once
|
||||
* @return boolean
|
||||
* @deprecated Since 1.5.0; use loadFile() instead
|
||||
*/
|
||||
protected static function _includeFile($filespec, $once = false)
|
||||
{
|
||||
if ($once) {
|
||||
return include_once $filespec;
|
||||
} else {
|
||||
return include $filespec ;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Standardise the filename.
|
||||
*
|
||||
* Convert the supplied filename into the namespace-aware standard,
|
||||
* based on the Framework Interop Group reference implementation:
|
||||
* http://groups.google.com/group/php-standards/web/psr-0-final-proposal
|
||||
*
|
||||
* The filename must be formatted as "$file.php".
|
||||
*
|
||||
* @param string $file - The file name to be loaded.
|
||||
* @return string
|
||||
*/
|
||||
public static function standardiseFile($file)
|
||||
{
|
||||
$fileName = ltrim($file, '\\');
|
||||
$file = '';
|
||||
$namespace = '';
|
||||
if ($lastNsPos = strripos($fileName, '\\')) {
|
||||
$namespace = substr($fileName, 0, $lastNsPos);
|
||||
$fileName = substr($fileName, $lastNsPos + 1);
|
||||
$file = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
|
||||
}
|
||||
$file .= str_replace('_', DIRECTORY_SEPARATOR, $fileName) . '.php';
|
||||
return $file;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,589 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Loader
|
||||
* @subpackage Autoloader
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @version $Id$
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
/** Postman_Zend_Loader */
|
||||
require_once 'Zend/Loader.php';
|
||||
|
||||
/**
|
||||
* Autoloader stack and namespace autoloader
|
||||
*
|
||||
* @uses Postman_Zend_Loader_Autoloader
|
||||
* @package Postman_Zend_Loader
|
||||
* @subpackage Autoloader
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Postman_Zend_Loader_Autoloader
|
||||
{
|
||||
/**
|
||||
* @var Postman_Zend_Loader_Autoloader Singleton instance
|
||||
*/
|
||||
protected static $_instance;
|
||||
|
||||
/**
|
||||
* @var array Concrete autoloader callback implementations
|
||||
*/
|
||||
protected $_autoloaders = array();
|
||||
|
||||
/**
|
||||
* @var array Default autoloader callback
|
||||
*/
|
||||
protected $_defaultAutoloader = array('Postman_Zend_Loader', 'loadClass');
|
||||
|
||||
/**
|
||||
* @var bool Whether or not to act as a fallback autoloader
|
||||
*/
|
||||
protected $_fallbackAutoloader = false;
|
||||
|
||||
/**
|
||||
* @var array Callback for internal autoloader implementation
|
||||
*/
|
||||
protected $_internalAutoloader;
|
||||
|
||||
/**
|
||||
* @var array Supported namespaces 'Zend' and 'ZendX' by default.
|
||||
*/
|
||||
protected $_namespaces = array(
|
||||
'Postman_Zend_' => true,
|
||||
'ZendX_' => true,
|
||||
);
|
||||
|
||||
/**
|
||||
* @var array Namespace-specific autoloaders
|
||||
*/
|
||||
protected $_namespaceAutoloaders = array();
|
||||
|
||||
/**
|
||||
* @var bool Whether or not to suppress file not found warnings
|
||||
*/
|
||||
protected $_suppressNotFoundWarnings = false;
|
||||
|
||||
/**
|
||||
* @var null|string
|
||||
*/
|
||||
protected $_zfPath;
|
||||
|
||||
/**
|
||||
* Retrieve singleton instance
|
||||
*
|
||||
* @return Postman_Zend_Loader_Autoloader
|
||||
*/
|
||||
public static function getInstance()
|
||||
{
|
||||
if (null === self::$_instance) {
|
||||
self::$_instance = new self();
|
||||
}
|
||||
return self::$_instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the singleton instance
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function resetInstance()
|
||||
{
|
||||
self::$_instance = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Autoload a class
|
||||
*
|
||||
* @param string $class
|
||||
* @return bool
|
||||
*/
|
||||
public static function autoload($class)
|
||||
{
|
||||
$self = self::getInstance();
|
||||
|
||||
foreach ($self->getClassAutoloaders($class) as $autoloader) {
|
||||
if ($autoloader instanceof Postman_Zend_Loader_Autoloader_Interface) {
|
||||
if ($autoloader->autoload($class)) {
|
||||
return true;
|
||||
}
|
||||
} elseif (is_array($autoloader)) {
|
||||
if (call_user_func($autoloader, $class)) {
|
||||
return true;
|
||||
}
|
||||
} elseif (is_string($autoloader) || is_callable($autoloader)) {
|
||||
if ($autoloader($class)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default autoloader implementation
|
||||
*
|
||||
* @param string|array $callback PHP callback
|
||||
* @return void
|
||||
*/
|
||||
public function setDefaultAutoloader($callback)
|
||||
{
|
||||
if (!is_callable($callback)) {
|
||||
throw new Postman_Zend_Loader_Exception('Invalid callback specified for default autoloader');
|
||||
}
|
||||
|
||||
$this->_defaultAutoloader = $callback;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the default autoloader callback
|
||||
*
|
||||
* @return string|array PHP Callback
|
||||
*/
|
||||
public function getDefaultAutoloader()
|
||||
{
|
||||
return $this->_defaultAutoloader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set several autoloader callbacks at once
|
||||
*
|
||||
* @param array $autoloaders Array of PHP callbacks (or Postman_Zend_Loader_Autoloader_Interface implementations) to act as autoloaders
|
||||
* @return Postman_Zend_Loader_Autoloader
|
||||
*/
|
||||
public function setAutoloaders(array $autoloaders)
|
||||
{
|
||||
$this->_autoloaders = $autoloaders;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get attached autoloader implementations
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getAutoloaders()
|
||||
{
|
||||
return $this->_autoloaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all autoloaders for a given namespace
|
||||
*
|
||||
* @param string $namespace
|
||||
* @return array
|
||||
*/
|
||||
public function getNamespaceAutoloaders($namespace)
|
||||
{
|
||||
$namespace = (string) $namespace;
|
||||
if (!array_key_exists($namespace, $this->_namespaceAutoloaders)) {
|
||||
return array();
|
||||
}
|
||||
return $this->_namespaceAutoloaders[$namespace];
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a namespace to autoload
|
||||
*
|
||||
* @param string|array $namespace
|
||||
* @return Postman_Zend_Loader_Autoloader
|
||||
*/
|
||||
public function registerNamespace($namespace)
|
||||
{
|
||||
if (is_string($namespace)) {
|
||||
$namespace = (array) $namespace;
|
||||
} elseif (!is_array($namespace)) {
|
||||
throw new Postman_Zend_Loader_Exception('Invalid namespace provided');
|
||||
}
|
||||
|
||||
foreach ($namespace as $ns) {
|
||||
if (!isset($this->_namespaces[$ns])) {
|
||||
$this->_namespaces[$ns] = true;
|
||||
}
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unload a registered autoload namespace
|
||||
*
|
||||
* @param string|array $namespace
|
||||
* @return Postman_Zend_Loader_Autoloader
|
||||
*/
|
||||
public function unregisterNamespace($namespace)
|
||||
{
|
||||
if (is_string($namespace)) {
|
||||
$namespace = (array) $namespace;
|
||||
} elseif (!is_array($namespace)) {
|
||||
throw new Postman_Zend_Loader_Exception('Invalid namespace provided');
|
||||
}
|
||||
|
||||
foreach ($namespace as $ns) {
|
||||
if (isset($this->_namespaces[$ns])) {
|
||||
unset($this->_namespaces[$ns]);
|
||||
}
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of registered autoload namespaces
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getRegisteredNamespaces()
|
||||
{
|
||||
return array_keys($this->_namespaces);
|
||||
}
|
||||
|
||||
public function setZfPath($spec, $version = 'latest')
|
||||
{
|
||||
$path = $spec;
|
||||
if (is_array($spec)) {
|
||||
if (!isset($spec['path'])) {
|
||||
throw new Postman_Zend_Loader_Exception('No path specified for ZF');
|
||||
}
|
||||
$path = $spec['path'];
|
||||
if (isset($spec['version'])) {
|
||||
$version = $spec['version'];
|
||||
}
|
||||
}
|
||||
|
||||
$this->_zfPath = $this->_getVersionPath($path, $version);
|
||||
set_include_path(implode(PATH_SEPARATOR, array(
|
||||
$this->_zfPath,
|
||||
get_include_path(),
|
||||
)));
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getZfPath()
|
||||
{
|
||||
return $this->_zfPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get or set the value of the "suppress not found warnings" flag
|
||||
*
|
||||
* @param null|bool $flag
|
||||
* @return bool|Postman_Zend_Loader_Autoloader Returns boolean if no argument is passed, object instance otherwise
|
||||
*/
|
||||
public function suppressNotFoundWarnings($flag = null)
|
||||
{
|
||||
if (null === $flag) {
|
||||
return $this->_suppressNotFoundWarnings;
|
||||
}
|
||||
$this->_suppressNotFoundWarnings = (bool) $flag;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicate whether or not this autoloader should be a fallback autoloader
|
||||
*
|
||||
* @param bool $flag
|
||||
* @return Postman_Zend_Loader_Autoloader
|
||||
*/
|
||||
public function setFallbackAutoloader($flag)
|
||||
{
|
||||
$this->_fallbackAutoloader = (bool) $flag;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this instance acting as a fallback autoloader?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isFallbackAutoloader()
|
||||
{
|
||||
return $this->_fallbackAutoloader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get autoloaders to use when matching class
|
||||
*
|
||||
* Determines if the class matches a registered namespace, and, if so,
|
||||
* returns only the autoloaders for that namespace. Otherwise, it returns
|
||||
* all non-namespaced autoloaders.
|
||||
*
|
||||
* @param string $class
|
||||
* @return array Array of autoloaders to use
|
||||
*/
|
||||
public function getClassAutoloaders($class)
|
||||
{
|
||||
$namespace = false;
|
||||
$autoloaders = array();
|
||||
|
||||
// Add concrete namespaced autoloaders
|
||||
foreach (array_keys($this->_namespaceAutoloaders) as $ns) {
|
||||
if ('' == $ns) {
|
||||
continue;
|
||||
}
|
||||
if (0 === strpos($class, $ns)) {
|
||||
if ((false === $namespace) || (strlen($ns) > strlen($namespace))) {
|
||||
$namespace = $ns;
|
||||
$autoloaders = $this->getNamespaceAutoloaders($ns);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add internal namespaced autoloader
|
||||
foreach ($this->getRegisteredNamespaces() as $ns) {
|
||||
if (0 === strpos($class, $ns)) {
|
||||
$namespace = $ns;
|
||||
$autoloaders[] = $this->_internalAutoloader;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Add non-namespaced autoloaders
|
||||
$autoloadersNonNamespace = $this->getNamespaceAutoloaders('');
|
||||
if (count($autoloadersNonNamespace)) {
|
||||
foreach ($autoloadersNonNamespace as $ns) {
|
||||
$autoloaders[] = $ns;
|
||||
}
|
||||
unset($autoloadersNonNamespace);
|
||||
}
|
||||
|
||||
// Add fallback autoloader
|
||||
if (!$namespace && $this->isFallbackAutoloader()) {
|
||||
$autoloaders[] = $this->_internalAutoloader;
|
||||
}
|
||||
|
||||
return $autoloaders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an autoloader to the beginning of the stack
|
||||
*
|
||||
* @param object|array|string $callback PHP callback or Postman_Zend_Loader_Autoloader_Interface implementation
|
||||
* @param string|array $namespace Specific namespace(s) under which to register callback
|
||||
* @return Postman_Zend_Loader_Autoloader
|
||||
*/
|
||||
public function unshiftAutoloader($callback, $namespace = '')
|
||||
{
|
||||
$autoloaders = $this->getAutoloaders();
|
||||
array_unshift($autoloaders, $callback);
|
||||
$this->setAutoloaders($autoloaders);
|
||||
|
||||
$namespace = (array) $namespace;
|
||||
foreach ($namespace as $ns) {
|
||||
$autoloaders = $this->getNamespaceAutoloaders($ns);
|
||||
array_unshift($autoloaders, $callback);
|
||||
$this->_setNamespaceAutoloaders($autoloaders, $ns);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Append an autoloader to the autoloader stack
|
||||
*
|
||||
* @param object|array|string $callback PHP callback or Postman_Zend_Loader_Autoloader_Interface implementation
|
||||
* @param string|array $namespace Specific namespace(s) under which to register callback
|
||||
* @return Postman_Zend_Loader_Autoloader
|
||||
*/
|
||||
public function pushAutoloader($callback, $namespace = '')
|
||||
{
|
||||
$autoloaders = $this->getAutoloaders();
|
||||
array_push($autoloaders, $callback);
|
||||
$this->setAutoloaders($autoloaders);
|
||||
|
||||
$namespace = (array) $namespace;
|
||||
foreach ($namespace as $ns) {
|
||||
$autoloaders = $this->getNamespaceAutoloaders($ns);
|
||||
array_push($autoloaders, $callback);
|
||||
$this->_setNamespaceAutoloaders($autoloaders, $ns);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an autoloader from the autoloader stack
|
||||
*
|
||||
* @param object|array|string $callback PHP callback or Postman_Zend_Loader_Autoloader_Interface implementation
|
||||
* @param null|string|array $namespace Specific namespace(s) from which to remove autoloader
|
||||
* @return Postman_Zend_Loader_Autoloader
|
||||
*/
|
||||
public function removeAutoloader($callback, $namespace = null)
|
||||
{
|
||||
if (null === $namespace) {
|
||||
$autoloaders = $this->getAutoloaders();
|
||||
if (false !== ($index = array_search($callback, $autoloaders, true))) {
|
||||
unset($autoloaders[$index]);
|
||||
$this->setAutoloaders($autoloaders);
|
||||
}
|
||||
|
||||
foreach ($this->_namespaceAutoloaders as $ns => $autoloaders) {
|
||||
if (false !== ($index = array_search($callback, $autoloaders, true))) {
|
||||
unset($autoloaders[$index]);
|
||||
$this->_setNamespaceAutoloaders($autoloaders, $ns);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$namespace = (array) $namespace;
|
||||
foreach ($namespace as $ns) {
|
||||
$autoloaders = $this->getNamespaceAutoloaders($ns);
|
||||
if (false !== ($index = array_search($callback, $autoloaders, true))) {
|
||||
unset($autoloaders[$index]);
|
||||
$this->_setNamespaceAutoloaders($autoloaders, $ns);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* Registers instance with spl_autoload stack
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function __construct()
|
||||
{
|
||||
spl_autoload_register(array(__CLASS__, 'autoload'));
|
||||
$this->_internalAutoloader = array($this, '_autoload');
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal autoloader implementation
|
||||
*
|
||||
* @param string $class
|
||||
* @return bool
|
||||
*/
|
||||
protected function _autoload($class)
|
||||
{
|
||||
$callback = $this->getDefaultAutoloader();
|
||||
try {
|
||||
if ($this->suppressNotFoundWarnings()) {
|
||||
@call_user_func($callback, $class);
|
||||
} else {
|
||||
call_user_func($callback, $class);
|
||||
}
|
||||
return $class;
|
||||
} catch (Postman_Zend_Exception $e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set autoloaders for a specific namespace
|
||||
*
|
||||
* @param array $autoloaders
|
||||
* @param string $namespace
|
||||
* @return Postman_Zend_Loader_Autoloader
|
||||
*/
|
||||
protected function _setNamespaceAutoloaders(array $autoloaders, $namespace = '')
|
||||
{
|
||||
$namespace = (string) $namespace;
|
||||
$this->_namespaceAutoloaders[$namespace] = $autoloaders;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the filesystem path for the requested ZF version
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $version
|
||||
* @return void
|
||||
*/
|
||||
protected function _getVersionPath($path, $version)
|
||||
{
|
||||
$type = $this->_getVersionType($version);
|
||||
|
||||
if ($type == 'latest') {
|
||||
$version = 'latest';
|
||||
}
|
||||
|
||||
$availableVersions = $this->_getAvailableVersions($path, $version);
|
||||
if (empty($availableVersions)) {
|
||||
throw new Postman_Zend_Loader_Exception('No valid ZF installations discovered');
|
||||
}
|
||||
|
||||
$matchedVersion = array_pop($availableVersions);
|
||||
return $matchedVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the ZF version type
|
||||
*
|
||||
* @param string $version
|
||||
* @return string "latest", "major", "minor", or "specific"
|
||||
* @throws Postman_Zend_Loader_Exception if version string contains too many dots
|
||||
*/
|
||||
protected function _getVersionType($version)
|
||||
{
|
||||
if (strtolower($version) == 'latest') {
|
||||
return 'latest';
|
||||
}
|
||||
|
||||
$parts = explode('.', $version);
|
||||
$count = count($parts);
|
||||
if (1 == $count) {
|
||||
return 'major';
|
||||
}
|
||||
if (2 == $count) {
|
||||
return 'minor';
|
||||
}
|
||||
if (3 < $count) {
|
||||
throw new Postman_Zend_Loader_Exception('Invalid version string provided');
|
||||
}
|
||||
return 'specific';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get available versions for the version type requested
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $version
|
||||
* @return array
|
||||
*/
|
||||
protected function _getAvailableVersions($path, $version)
|
||||
{
|
||||
if (!is_dir($path)) {
|
||||
throw new Postman_Zend_Loader_Exception('Invalid ZF path provided');
|
||||
}
|
||||
|
||||
$path = rtrim($path, '/');
|
||||
$path = rtrim($path, '\\');
|
||||
$versionLen = strlen($version);
|
||||
$versions = array();
|
||||
$dirs = glob("$path/*", GLOB_ONLYDIR);
|
||||
foreach ((array) $dirs as $dir) {
|
||||
$dirName = substr($dir, strlen($path) + 1);
|
||||
if (!preg_match('/^(?:ZendFramework-)?(\d+\.\d+\.\d+((a|b|pl|pr|p|rc)\d+)?)(?:-minimal)?$/i', $dirName, $matches)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$matchedVersion = $matches[1];
|
||||
|
||||
if (('latest' == $version)
|
||||
|| ((strlen($matchedVersion) >= $versionLen)
|
||||
&& (0 === strpos($matchedVersion, $version)))
|
||||
) {
|
||||
$versions[$matchedVersion] = $dir . '/library';
|
||||
}
|
||||
}
|
||||
|
||||
uksort($versions, 'version_compare');
|
||||
return $versions;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Exception
|
||||
*/
|
||||
// require_once 'Zend/Exception.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Postman_Zend_Mail_Exception extends Postman_Zend_Exception
|
||||
{}
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Postman_Zend_Mail_Part
|
||||
*/
|
||||
require_once 'Zend/Mail/Part.php';
|
||||
|
||||
/**
|
||||
* Postman_Zend_Mail_Message_Interface
|
||||
*/
|
||||
require_once 'Zend/Mail/Message/Interface.php';
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Postman_Zend_Mail_Message extends Postman_Zend_Mail_Part implements Postman_Zend_Mail_Message_Interface
|
||||
{
|
||||
/**
|
||||
* flags for this message
|
||||
* @var array
|
||||
*/
|
||||
protected $_flags = array();
|
||||
|
||||
/**
|
||||
* Public constructor
|
||||
*
|
||||
* In addition to the parameters of Postman_Zend_Mail_Part::__construct() this constructor supports:
|
||||
* - file filename or file handle of a file with raw message content
|
||||
* - flags array with flags for message, keys are ignored, use constants defined in Postman_Zend_Mail_Storage
|
||||
*
|
||||
* @param string $rawMessage full message with or without headers
|
||||
* @throws Postman_Zend_Mail_Exception
|
||||
*/
|
||||
public function __construct(array $params)
|
||||
{
|
||||
if (isset($params['file'])) {
|
||||
if (!is_resource($params['file'])) {
|
||||
$params['raw'] = @file_get_contents($params['file']);
|
||||
if ($params['raw'] === false) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Exception.php';
|
||||
throw new Postman_Zend_Mail_Exception('could not open file');
|
||||
}
|
||||
} else {
|
||||
$params['raw'] = stream_get_contents($params['file']);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($params['flags'])) {
|
||||
// set key and value to the same value for easy lookup
|
||||
$this->_flags = array_merge($this->_flags, array_combine($params['flags'],$params['flags']));
|
||||
}
|
||||
|
||||
parent::__construct($params);
|
||||
}
|
||||
|
||||
/**
|
||||
* return toplines as found after headers
|
||||
*
|
||||
* @return string toplines
|
||||
*/
|
||||
public function getTopLines()
|
||||
{
|
||||
return $this->_topLines;
|
||||
}
|
||||
|
||||
/**
|
||||
* check if flag is set
|
||||
*
|
||||
* @param mixed $flag a flag name, use constants defined in Postman_Zend_Mail_Storage
|
||||
* @return bool true if set, otherwise false
|
||||
*/
|
||||
public function hasFlag($flag)
|
||||
{
|
||||
return isset($this->_flags[$flag]);
|
||||
}
|
||||
|
||||
/**
|
||||
* get all set flags
|
||||
*
|
||||
* @return array array with flags, key and value are the same for easy lookup
|
||||
*/
|
||||
public function getFlags()
|
||||
{
|
||||
return $this->_flags;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Postman_Zend_Mail_Part
|
||||
*/
|
||||
require_once 'Zend/Mail/Part/File.php';
|
||||
|
||||
/**
|
||||
* Postman_Zend_Mail_Message_Interface
|
||||
*/
|
||||
require_once 'Zend/Mail/Message/Interface.php';
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Postman_Zend_Mail_Message_File extends Postman_Zend_Mail_Part_File implements Postman_Zend_Mail_Message_Interface
|
||||
{
|
||||
/**
|
||||
* flags for this message
|
||||
* @var array
|
||||
*/
|
||||
protected $_flags = array();
|
||||
|
||||
/**
|
||||
* Public constructor
|
||||
*
|
||||
* In addition to the parameters of Postman_Zend_Mail_Part::__construct() this constructor supports:
|
||||
* - flags array with flags for message, keys are ignored, use constants defined in Postman_Zend_Mail_Storage
|
||||
*
|
||||
* @param string $rawMessage full message with or without headers
|
||||
* @throws Postman_Zend_Mail_Exception
|
||||
*/
|
||||
public function __construct(array $params)
|
||||
{
|
||||
if (!empty($params['flags'])) {
|
||||
// set key and value to the same value for easy lookup
|
||||
$this->_flags = array_combine($params['flags'], $params['flags']);
|
||||
}
|
||||
|
||||
parent::__construct($params);
|
||||
}
|
||||
|
||||
/**
|
||||
* return toplines as found after headers
|
||||
*
|
||||
* @return string toplines
|
||||
*/
|
||||
public function getTopLines()
|
||||
{
|
||||
return $this->_topLines;
|
||||
}
|
||||
|
||||
/**
|
||||
* check if flag is set
|
||||
*
|
||||
* @param mixed $flag a flag name, use constants defined in Postman_Zend_Mail_Storage
|
||||
* @return bool true if set, otherwise false
|
||||
*/
|
||||
public function hasFlag($flag)
|
||||
{
|
||||
return isset($this->_flags[$flag]);
|
||||
}
|
||||
|
||||
/**
|
||||
* get all set flags
|
||||
*
|
||||
* @return array array with flags, key and value are the same for easy lookup
|
||||
*/
|
||||
public function getFlags()
|
||||
{
|
||||
return $this->_flags;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Storage
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Storage
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
interface Postman_Zend_Mail_Message_Interface
|
||||
{
|
||||
/**
|
||||
* return toplines as found after headers
|
||||
*
|
||||
* @return string toplines
|
||||
*/
|
||||
public function getTopLines();
|
||||
|
||||
/**
|
||||
* check if flag is set
|
||||
*
|
||||
* @param mixed $flag a flag name, use constants defined in Postman_Zend_Mail_Storage
|
||||
* @return bool true if set, otherwise false
|
||||
*/
|
||||
public function hasFlag($flag);
|
||||
|
||||
/**
|
||||
* get all set flags
|
||||
*
|
||||
* @return array array with flags, key and value are the same for easy lookup
|
||||
*/
|
||||
public function getFlags();
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mime_Decode
|
||||
*/
|
||||
require_once 'Zend/Mime/Decode.php';
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Part
|
||||
*/
|
||||
require_once 'Zend/Mail/Part.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Postman_Zend_Mail_Part_File extends Postman_Zend_Mail_Part
|
||||
{
|
||||
protected $_contentPos = array();
|
||||
protected $_partPos = array();
|
||||
protected $_fh;
|
||||
|
||||
/**
|
||||
* Public constructor
|
||||
*
|
||||
* This handler supports the following params:
|
||||
* - file filename or open file handler with message content (required)
|
||||
* - startPos start position of message or part in file (default: current position)
|
||||
* - endPos end position of message or part in file (default: end of file)
|
||||
*
|
||||
* @param array $params full message with or without headers
|
||||
* @throws Postman_Zend_Mail_Exception
|
||||
*/
|
||||
public function __construct(array $params)
|
||||
{
|
||||
if (empty($params['file'])) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Exception.php';
|
||||
throw new Postman_Zend_Mail_Exception('no file given in params');
|
||||
}
|
||||
|
||||
if (!is_resource($params['file'])) {
|
||||
$this->_fh = fopen($params['file'], 'r');
|
||||
} else {
|
||||
$this->_fh = $params['file'];
|
||||
}
|
||||
if (!$this->_fh) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Exception.php';
|
||||
throw new Postman_Zend_Mail_Exception('could not open file');
|
||||
}
|
||||
if (isset($params['startPos'])) {
|
||||
fseek($this->_fh, $params['startPos']);
|
||||
}
|
||||
$header = '';
|
||||
$endPos = isset($params['endPos']) ? $params['endPos'] : null;
|
||||
while (($endPos === null || ftell($this->_fh) < $endPos) && trim($line = fgets($this->_fh))) {
|
||||
$header .= $line;
|
||||
}
|
||||
|
||||
Postman_Zend_Mime_Decode::splitMessage($header, $this->_headers, $null);
|
||||
|
||||
$this->_contentPos[0] = ftell($this->_fh);
|
||||
if ($endPos !== null) {
|
||||
$this->_contentPos[1] = $endPos;
|
||||
} else {
|
||||
fseek($this->_fh, 0, SEEK_END);
|
||||
$this->_contentPos[1] = ftell($this->_fh);
|
||||
}
|
||||
if (!$this->isMultipart()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$boundary = $this->getHeaderField('content-type', 'boundary');
|
||||
if (!$boundary) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Exception.php';
|
||||
throw new Postman_Zend_Mail_Exception('no boundary found in content type to split message');
|
||||
}
|
||||
|
||||
$part = array();
|
||||
$pos = $this->_contentPos[0];
|
||||
fseek($this->_fh, $pos);
|
||||
while (!feof($this->_fh) && ($endPos === null || $pos < $endPos)) {
|
||||
$line = fgets($this->_fh);
|
||||
if ($line === false) {
|
||||
if (feof($this->_fh)) {
|
||||
break;
|
||||
}
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Exception.php';
|
||||
throw new Postman_Zend_Mail_Exception('error reading file');
|
||||
}
|
||||
|
||||
$lastPos = $pos;
|
||||
$pos = ftell($this->_fh);
|
||||
$line = trim($line);
|
||||
|
||||
if ($line == '--' . $boundary) {
|
||||
if ($part) {
|
||||
// not first part
|
||||
$part[1] = $lastPos;
|
||||
$this->_partPos[] = $part;
|
||||
}
|
||||
$part = array($pos);
|
||||
} else if ($line == '--' . $boundary . '--') {
|
||||
$part[1] = $lastPos;
|
||||
$this->_partPos[] = $part;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$this->_countParts = count($this->_partPos);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Body of part
|
||||
*
|
||||
* If part is multipart the raw content of this part with all sub parts is returned
|
||||
*
|
||||
* @return string body
|
||||
* @throws Postman_Zend_Mail_Exception
|
||||
*/
|
||||
public function getContent($stream = null)
|
||||
{
|
||||
fseek($this->_fh, $this->_contentPos[0]);
|
||||
if ($stream !== null) {
|
||||
return stream_copy_to_stream($this->_fh, $stream, $this->_contentPos[1] - $this->_contentPos[0]);
|
||||
}
|
||||
$length = $this->_contentPos[1] - $this->_contentPos[0];
|
||||
return $length < 1 ? '' : fread($this->_fh, $length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return size of part
|
||||
*
|
||||
* Quite simple implemented currently (not decoding). Handle with care.
|
||||
*
|
||||
* @return int size
|
||||
*/
|
||||
public function getSize() {
|
||||
return $this->_contentPos[1] - $this->_contentPos[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get part of multipart message
|
||||
*
|
||||
* @param int $num number of part starting with 1 for first part
|
||||
* @return Postman_Zend_Mail_Part wanted part
|
||||
* @throws Postman_Zend_Mail_Exception
|
||||
*/
|
||||
public function getPart($num)
|
||||
{
|
||||
--$num;
|
||||
if (!isset($this->_partPos[$num])) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Exception.php';
|
||||
throw new Postman_Zend_Mail_Exception('part not found');
|
||||
}
|
||||
|
||||
return new self(array('file' => $this->_fh, 'startPos' => $this->_partPos[$num][0],
|
||||
'endPos' => $this->_partPos[$num][1]));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Storage
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Storage
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
interface Postman_Zend_Mail_Part_Interface extends RecursiveIterator
|
||||
{
|
||||
/**
|
||||
* Check if part is a multipart message
|
||||
*
|
||||
* @return bool if part is multipart
|
||||
*/
|
||||
public function isMultipart();
|
||||
|
||||
|
||||
/**
|
||||
* Body of part
|
||||
*
|
||||
* If part is multipart the raw content of this part with all sub parts is returned
|
||||
*
|
||||
* @return string body
|
||||
* @throws Postman_Zend_Mail_Exception
|
||||
*/
|
||||
public function getContent();
|
||||
|
||||
/**
|
||||
* Return size of part
|
||||
*
|
||||
* @return int size
|
||||
*/
|
||||
public function getSize();
|
||||
|
||||
/**
|
||||
* Get part of multipart message
|
||||
*
|
||||
* @param int $num number of part starting with 1 for first part
|
||||
* @return Postman_Zend_Mail_Part wanted part
|
||||
* @throws Postman_Zend_Mail_Exception
|
||||
*/
|
||||
public function getPart($num);
|
||||
|
||||
/**
|
||||
* Count parts of a multipart part
|
||||
*
|
||||
* @return int number of sub-parts
|
||||
*/
|
||||
public function countParts();
|
||||
|
||||
|
||||
/**
|
||||
* Get all headers
|
||||
*
|
||||
* The returned headers are as saved internally. All names are lowercased. The value is a string or an array
|
||||
* if a header with the same name occurs more than once.
|
||||
*
|
||||
* @return array headers as array(name => value)
|
||||
*/
|
||||
public function getHeaders();
|
||||
|
||||
/**
|
||||
* Get a header in specificed format
|
||||
*
|
||||
* Internally headers that occur more than once are saved as array, all other as string. If $format
|
||||
* is set to string implode is used to concat the values (with Postman_Zend_Mime::LINEEND as delim).
|
||||
*
|
||||
* @param string $name name of header, matches case-insensitive, but camel-case is replaced with dashes
|
||||
* @param string $format change type of return value to 'string' or 'array'
|
||||
* @return string|array value of header in wanted or internal format
|
||||
* @throws Postman_Zend_Mail_Exception
|
||||
*/
|
||||
public function getHeader($name, $format = null);
|
||||
|
||||
/**
|
||||
* Get a specific field from a header like content type or all fields as array
|
||||
*
|
||||
* If the header occurs more than once, only the value from the first header
|
||||
* is returned.
|
||||
*
|
||||
* Throws a Postman_Zend_Mail_Exception if the requested header does not exist. If
|
||||
* the specific header field does not exist, returns null.
|
||||
*
|
||||
* @param string $name name of header, like in getHeader()
|
||||
* @param string $wantedPart the wanted part, default is first, if null an array with all parts is returned
|
||||
* @param string $firstName key name for the first part
|
||||
* @return string|array wanted part or all parts as array($firstName => firstPart, partname => value)
|
||||
* @throws Postman_Zend_Exception, Postman_Zend_Mail_Exception
|
||||
*/
|
||||
public function getHeaderField($name, $wantedPart = 0, $firstName = 0);
|
||||
|
||||
|
||||
/**
|
||||
* Getter for mail headers - name is matched in lowercase
|
||||
*
|
||||
* This getter is short for Postman_Zend_Mail_Part::getHeader($name, 'string')
|
||||
*
|
||||
* @see Postman_Zend_Mail_Part::getHeader()
|
||||
*
|
||||
* @param string $name header name
|
||||
* @return string value of header
|
||||
* @throws Postman_Zend_Mail_Exception
|
||||
*/
|
||||
public function __get($name);
|
||||
|
||||
/**
|
||||
* magic method to get content of part
|
||||
*
|
||||
* @return string content
|
||||
*/
|
||||
public function __toString();
|
||||
}
|
||||
@@ -0,0 +1,453 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Protocol
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Validate
|
||||
*/
|
||||
// require_once 'Zend/Validate.php';
|
||||
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Validate_Hostname
|
||||
*/
|
||||
// require_once 'Zend/Validate/Hostname.php';
|
||||
|
||||
|
||||
/**
|
||||
* Postman_Zend_Mail_Protocol_Abstract
|
||||
*
|
||||
* Provides low-level methods for concrete adapters to communicate with a remote mail server and track requests and responses.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Protocol
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
* @todo Implement proxy settings
|
||||
*/
|
||||
abstract class Postman_Zend_Mail_Protocol_Abstract
|
||||
{
|
||||
/**
|
||||
* Mail default EOL string
|
||||
*/
|
||||
const EOL = "\r\n";
|
||||
|
||||
|
||||
/**
|
||||
* Default timeout in seconds for initiating session
|
||||
*/
|
||||
const TIMEOUT_CONNECTION = 30;
|
||||
|
||||
/**
|
||||
* Maximum of the transaction log
|
||||
* @var integer
|
||||
*/
|
||||
protected $_maximumLog = 64;
|
||||
|
||||
|
||||
/**
|
||||
* Hostname or IP address of remote server
|
||||
* @var string
|
||||
*/
|
||||
protected $_host;
|
||||
|
||||
|
||||
/**
|
||||
* Port number of connection
|
||||
* @var integer
|
||||
*/
|
||||
protected $_port;
|
||||
|
||||
|
||||
/**
|
||||
* Instance of Postman_Zend_Validate to check hostnames
|
||||
* @var Postman_Zend_Validate
|
||||
*/
|
||||
protected $_validHost;
|
||||
|
||||
|
||||
/**
|
||||
* Socket connection resource
|
||||
* @var resource
|
||||
*/
|
||||
protected $_socket;
|
||||
|
||||
|
||||
/**
|
||||
* Last request sent to server
|
||||
* @var string
|
||||
*/
|
||||
protected $_request;
|
||||
|
||||
|
||||
/**
|
||||
* Array of server responses to last request
|
||||
* @var array
|
||||
*/
|
||||
protected $_response;
|
||||
|
||||
|
||||
/**
|
||||
* String template for parsing server responses using sscanf (default: 3 digit code and response string)
|
||||
* @var resource
|
||||
* @deprecated Since 1.10.3
|
||||
*/
|
||||
protected $_template = '%d%s';
|
||||
|
||||
|
||||
/**
|
||||
* Log of mail requests and server responses for a session
|
||||
* @var array
|
||||
*/
|
||||
private $_log = array();
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $host OPTIONAL Hostname of remote connection (default: 127.0.0.1)
|
||||
* @param integer $port OPTIONAL Port number (default: null)
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($host = '127.0.0.1', $port = null)
|
||||
{
|
||||
$this->_validHost = new Postman_Zend_Validate();
|
||||
$this->_validHost->addValidator(new Postman_Zend_Validate_Hostname(Postman_Zend_Validate_Hostname::ALLOW_ALL));
|
||||
|
||||
if (!$this->_validHost->isValid($host)) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
// require_once 'Zend/Mail/Protocol/Exception.php';
|
||||
throw new Postman_Zend_Mail_Protocol_Exception(join(', ', $this->_validHost->getMessages()));
|
||||
}
|
||||
|
||||
$this->_host = $host;
|
||||
$this->_port = $port;
|
||||
$this->_maximumLog = PostmanOptions::getInstance()->getTranscriptSize();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class destructor to cleanup open resources
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
$this->_disconnect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum log size
|
||||
*
|
||||
* @param integer $maximumLog Maximum log size
|
||||
* @return void
|
||||
*/
|
||||
public function setMaximumLog($maximumLog)
|
||||
{
|
||||
$this->_maximumLog = (int) $maximumLog;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the maximum log size
|
||||
*
|
||||
* @return int the maximum log size
|
||||
*/
|
||||
public function getMaximumLog()
|
||||
{
|
||||
return $this->_maximumLog;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a connection to the remote host
|
||||
*
|
||||
* Concrete adapters for this class will implement their own unique connect scripts, using the _connect() method to create the socket resource.
|
||||
*/
|
||||
abstract public function connect();
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the last client request
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRequest()
|
||||
{
|
||||
return $this->_request;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the last server response
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getResponse()
|
||||
{
|
||||
return $this->_response;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieve the transaction log
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLog()
|
||||
{
|
||||
return implode('', $this->_log);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reset the transaction log
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function resetLog()
|
||||
{
|
||||
$this->_log = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the transaction log
|
||||
*
|
||||
* @param string new transaction
|
||||
* @return void
|
||||
*/
|
||||
protected function _addLog($value)
|
||||
{
|
||||
if ($this->_maximumLog >= 0 && count($this->_log) >= $this->_maximumLog) {
|
||||
array_shift($this->_log);
|
||||
}
|
||||
|
||||
$this->_log[] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect to the server using the supplied transport and target
|
||||
*
|
||||
* An example $remote string may be 'tcp://mail.example.com:25' or 'ssh://hostname.com:2222'
|
||||
*
|
||||
* @param string $remote Remote
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
* @return boolean
|
||||
*/
|
||||
protected function _connect($remote)
|
||||
{
|
||||
$errorNum = 0;
|
||||
$errorStr = '';
|
||||
|
||||
// open connection
|
||||
$this->_socket = @stream_socket_client($remote, $errorNum, $errorStr, self::TIMEOUT_CONNECTION);
|
||||
|
||||
if ($this->_socket === false) {
|
||||
if ($errorNum == 0) {
|
||||
$errorStr = 'Could not open socket';
|
||||
}
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
// require_once 'Zend/Mail/Protocol/Exception.php';
|
||||
throw new Postman_Zend_Mail_Protocol_Exception($errorStr);
|
||||
}
|
||||
|
||||
if (($result = $this->_setStreamTimeout(self::TIMEOUT_CONNECTION)) === false) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
// require_once 'Zend/Mail/Protocol/Exception.php';
|
||||
throw new Postman_Zend_Mail_Protocol_Exception('Could not set stream timeout');
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Disconnect from remote host and free resource
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function _disconnect()
|
||||
{
|
||||
if (is_resource($this->_socket)) {
|
||||
fclose($this->_socket);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send the given request followed by a LINEEND to the server.
|
||||
*
|
||||
* @param string $request
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
* @return integer|boolean Number of bytes written to remote host
|
||||
*/
|
||||
protected function _send($request)
|
||||
{
|
||||
if (!is_resource($this->_socket)) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
// require_once 'Zend/Mail/Protocol/Exception.php';
|
||||
throw new Postman_Zend_Mail_Protocol_Exception('No connection has been established to ' . $this->_host);
|
||||
}
|
||||
|
||||
$this->_request = $request;
|
||||
|
||||
$result = fwrite($this->_socket, $request . self::EOL);
|
||||
|
||||
// Save request to internal log
|
||||
$this->_addLog($request . self::EOL);
|
||||
|
||||
if ($result === false) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
// require_once 'Zend/Mail/Protocol/Exception.php';
|
||||
throw new Postman_Zend_Mail_Protocol_Exception('Could not send request to ' . $this->_host);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a line from the stream.
|
||||
*
|
||||
* @var integer $timeout Per-request timeout value if applicable
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
* @return string
|
||||
*/
|
||||
protected function _receive($timeout = null)
|
||||
{
|
||||
if (!is_resource($this->_socket)) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
// require_once 'Zend/Mail/Protocol/Exception.php';
|
||||
throw new Postman_Zend_Mail_Protocol_Exception('No connection has been established to ' . $this->_host);
|
||||
}
|
||||
|
||||
// Adapters may wish to supply per-commend timeouts according to appropriate RFC
|
||||
if ($timeout !== null) {
|
||||
$this->_setStreamTimeout($timeout);
|
||||
}
|
||||
|
||||
// Retrieve response
|
||||
$reponse = fgets($this->_socket, 1024);
|
||||
|
||||
// Save request to internal log
|
||||
$this->_addLog($reponse);
|
||||
|
||||
// Check meta data to ensure connection is still valid
|
||||
$info = stream_get_meta_data($this->_socket);
|
||||
|
||||
if (!empty($info['timed_out'])) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
// require_once 'Zend/Mail/Protocol/Exception.php';
|
||||
throw new Postman_Zend_Mail_Protocol_Exception($this->_host . ' has timed out');
|
||||
}
|
||||
|
||||
if ($reponse === false) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
// require_once 'Zend/Mail/Protocol/Exception.php';
|
||||
throw new Postman_Zend_Mail_Protocol_Exception('Could not read from ' . $this->_host);
|
||||
}
|
||||
|
||||
return $reponse;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set stream timeout
|
||||
*
|
||||
* @param integer $timeout
|
||||
* @return boolean
|
||||
*/
|
||||
protected function _setStreamTimeout($timeout)
|
||||
{
|
||||
// @jason: added @ to hide PHP warnings if the host has disabled stream_set_timeout
|
||||
return @stream_set_timeout($this->_socket, $timeout);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Protocol
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Exception
|
||||
*/
|
||||
// require_once 'Zend/Mail/Exception.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Protocol
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Postman_Zend_Mail_Protocol_Exception extends Postman_Zend_Mail_Exception
|
||||
{}
|
||||
|
||||
@@ -0,0 +1,838 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Protocol
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Protocol
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Postman_Zend_Mail_Protocol_Imap
|
||||
{
|
||||
/**
|
||||
* Default timeout in seconds for initiating session
|
||||
*/
|
||||
const TIMEOUT_CONNECTION = 30;
|
||||
|
||||
/**
|
||||
* socket to imap server
|
||||
* @var resource|null
|
||||
*/
|
||||
protected $_socket;
|
||||
|
||||
/**
|
||||
* counter for request tag
|
||||
* @var int
|
||||
*/
|
||||
protected $_tagCount = 0;
|
||||
|
||||
/**
|
||||
* Public constructor
|
||||
*
|
||||
* @param string $host hostname or IP address of IMAP server, if given connect() is called
|
||||
* @param int|null $port port of IMAP server, null for default (143 or 993 for ssl)
|
||||
* @param bool $ssl use ssl? 'SSL', 'TLS' or false
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
function __construct($host = '', $port = null, $ssl = false)
|
||||
{
|
||||
if ($host) {
|
||||
$this->connect($host, $port, $ssl);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Public destructor
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
$this->logout();
|
||||
}
|
||||
|
||||
/**
|
||||
* Open connection to IMAP server
|
||||
*
|
||||
* @param string $host hostname or IP address of IMAP server
|
||||
* @param int|null $port of IMAP server, default is 143 (993 for ssl)
|
||||
* @param string|bool $ssl use 'SSL', 'TLS' or false
|
||||
* @return string welcome message
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function connect($host, $port = null, $ssl = false)
|
||||
{
|
||||
if ($ssl == 'SSL') {
|
||||
$host = 'ssl://' . $host;
|
||||
}
|
||||
|
||||
if ($port === null) {
|
||||
$port = $ssl === 'SSL' ? 993 : 143;
|
||||
}
|
||||
|
||||
$errno = 0;
|
||||
$errstr = '';
|
||||
$this->_socket = @fsockopen($host, $port, $errno, $errstr, self::TIMEOUT_CONNECTION);
|
||||
if (!$this->_socket) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Protocol/Exception.php';
|
||||
throw new Postman_Zend_Mail_Protocol_Exception('cannot connect to host; error = ' . $errstr .
|
||||
' (errno = ' . $errno . ' )');
|
||||
}
|
||||
|
||||
if (!$this->_assumedNextLine('* OK')) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Protocol/Exception.php';
|
||||
throw new Postman_Zend_Mail_Protocol_Exception('host doesn\'t allow connection');
|
||||
}
|
||||
|
||||
if ($ssl === 'TLS') {
|
||||
$result = $this->requestAndResponse('STARTTLS');
|
||||
$result = $result && stream_socket_enable_crypto($this->_socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
|
||||
if (!$result) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Protocol/Exception.php';
|
||||
throw new Postman_Zend_Mail_Protocol_Exception('cannot enable TLS');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get the next line from socket with error checking, but nothing else
|
||||
*
|
||||
* @return string next line
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
protected function _nextLine()
|
||||
{
|
||||
$line = @fgets($this->_socket);
|
||||
if ($line === false) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Protocol/Exception.php';
|
||||
throw new Postman_Zend_Mail_Protocol_Exception('cannot read - connection closed?');
|
||||
}
|
||||
|
||||
return $line;
|
||||
}
|
||||
|
||||
/**
|
||||
* get next line and assume it starts with $start. some requests give a simple
|
||||
* feedback so we can quickly check if we can go on.
|
||||
*
|
||||
* @param string $start the first bytes we assume to be in the next line
|
||||
* @return bool line starts with $start
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
protected function _assumedNextLine($start)
|
||||
{
|
||||
$line = $this->_nextLine();
|
||||
return strpos($line, $start) === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* get next line and split the tag. that's the normal case for a response line
|
||||
*
|
||||
* @param string $tag tag of line is returned by reference
|
||||
* @return string next line
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
protected function _nextTaggedLine(&$tag)
|
||||
{
|
||||
$line = $this->_nextLine();
|
||||
|
||||
// seperate tag from line
|
||||
list($tag, $line) = explode(' ', $line, 2);
|
||||
|
||||
return $line;
|
||||
}
|
||||
|
||||
/**
|
||||
* split a given line in tokens. a token is literal of any form or a list
|
||||
*
|
||||
* @param string $line line to decode
|
||||
* @return array tokens, literals are returned as string, lists as array
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
protected function _decodeLine($line)
|
||||
{
|
||||
$tokens = array();
|
||||
$stack = array();
|
||||
|
||||
/*
|
||||
We start to decode the response here. The unterstood tokens are:
|
||||
literal
|
||||
"literal" or also "lit\\er\"al"
|
||||
{bytes}<NL>literal
|
||||
(literals*)
|
||||
All tokens are returned in an array. Literals in braces (the last unterstood
|
||||
token in the list) are returned as an array of tokens. I.e. the following response:
|
||||
"foo" baz {3}<NL>bar ("f\\\"oo" bar)
|
||||
would be returned as:
|
||||
array('foo', 'baz', 'bar', array('f\\\"oo', 'bar'));
|
||||
|
||||
// TODO: add handling of '[' and ']' to parser for easier handling of response text
|
||||
*/
|
||||
// replace any trailling <NL> including spaces with a single space
|
||||
$line = rtrim($line) . ' ';
|
||||
while (($pos = strpos($line, ' ')) !== false) {
|
||||
$token = substr($line, 0, $pos);
|
||||
while ($token[0] == '(') {
|
||||
array_push($stack, $tokens);
|
||||
$tokens = array();
|
||||
$token = substr($token, 1);
|
||||
}
|
||||
if ($token[0] == '"') {
|
||||
if (preg_match('%^\(*"((.|\\\\|\\")*?)" *%', $line, $matches)) {
|
||||
$tokens[] = $matches[1];
|
||||
$line = substr($line, strlen($matches[0]));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ($token[0] == '{') {
|
||||
$endPos = strpos($token, '}');
|
||||
$chars = substr($token, 1, $endPos - 1);
|
||||
if (is_numeric($chars)) {
|
||||
$token = '';
|
||||
while (strlen($token) < $chars) {
|
||||
$token .= $this->_nextLine();
|
||||
}
|
||||
$line = '';
|
||||
if (strlen($token) > $chars) {
|
||||
$line = substr($token, $chars);
|
||||
$token = substr($token, 0, $chars);
|
||||
} else {
|
||||
$line .= $this->_nextLine();
|
||||
}
|
||||
$tokens[] = $token;
|
||||
$line = trim($line) . ' ';
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ($stack && $token[strlen($token) - 1] == ')') {
|
||||
// closing braces are not seperated by spaces, so we need to count them
|
||||
$braces = strlen($token);
|
||||
$token = rtrim($token, ')');
|
||||
// only count braces if more than one
|
||||
$braces -= strlen($token) + 1;
|
||||
// only add if token had more than just closing braces
|
||||
if (rtrim($token) != '') {
|
||||
$tokens[] = rtrim($token);
|
||||
}
|
||||
$token = $tokens;
|
||||
$tokens = array_pop($stack);
|
||||
// special handline if more than one closing brace
|
||||
while ($braces-- > 0) {
|
||||
$tokens[] = $token;
|
||||
$token = $tokens;
|
||||
$tokens = array_pop($stack);
|
||||
}
|
||||
}
|
||||
$tokens[] = $token;
|
||||
$line = substr($line, $pos + 1);
|
||||
}
|
||||
|
||||
// maybe the server forgot to send some closing braces
|
||||
while ($stack) {
|
||||
$child = $tokens;
|
||||
$tokens = array_pop($stack);
|
||||
$tokens[] = $child;
|
||||
}
|
||||
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* read a response "line" (could also be more than one real line if response has {..}<NL>)
|
||||
* and do a simple decode
|
||||
*
|
||||
* @param array|string $tokens decoded tokens are returned by reference, if $dontParse
|
||||
* is true the unparsed line is returned here
|
||||
* @param string $wantedTag check for this tag for response code. Default '*' is
|
||||
* continuation tag.
|
||||
* @param bool $dontParse if true only the unparsed line is returned $tokens
|
||||
* @return bool if returned tag matches wanted tag
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function readLine(&$tokens = array(), $wantedTag = '*', $dontParse = false)
|
||||
{
|
||||
$line = $this->_nextTaggedLine($tag);
|
||||
if (!$dontParse) {
|
||||
$tokens = $this->_decodeLine($line);
|
||||
} else {
|
||||
$tokens = $line;
|
||||
}
|
||||
|
||||
// if tag is wanted tag we might be at the end of a multiline response
|
||||
return $tag == $wantedTag;
|
||||
}
|
||||
|
||||
/**
|
||||
* read all lines of response until given tag is found (last line of response)
|
||||
*
|
||||
* @param string $tag the tag of your request
|
||||
* @param string|array $filter you can filter the response so you get only the
|
||||
* given response lines
|
||||
* @param bool $dontParse if true every line is returned unparsed instead of
|
||||
* the decoded tokens
|
||||
* @return null|bool|array tokens if success, false if error, null if bad request
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function readResponse($tag, $dontParse = false)
|
||||
{
|
||||
$lines = array();
|
||||
while (!$this->readLine($tokens, $tag, $dontParse)) {
|
||||
$lines[] = $tokens;
|
||||
}
|
||||
|
||||
if ($dontParse) {
|
||||
// last to chars are still needed for response code
|
||||
$tokens = array(substr($tokens, 0, 2));
|
||||
}
|
||||
// last line has response code
|
||||
if ($tokens[0] == 'OK') {
|
||||
return $lines ? $lines : true;
|
||||
} else if ($tokens[0] == 'NO'){
|
||||
return false;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* send a request
|
||||
*
|
||||
* @param string $command your request command
|
||||
* @param array $tokens additional parameters to command, use escapeString() to prepare
|
||||
* @param string $tag provide a tag otherwise an autogenerated is returned
|
||||
* @return null
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function sendRequest($command, $tokens = array(), &$tag = null)
|
||||
{
|
||||
if (!$tag) {
|
||||
++$this->_tagCount;
|
||||
$tag = 'TAG' . $this->_tagCount;
|
||||
}
|
||||
|
||||
$line = $tag . ' ' . $command;
|
||||
|
||||
foreach ($tokens as $token) {
|
||||
if (is_array($token)) {
|
||||
if (@fputs($this->_socket, $line . ' ' . $token[0] . "\r\n") === false) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Protocol/Exception.php';
|
||||
throw new Postman_Zend_Mail_Protocol_Exception('cannot write - connection closed?');
|
||||
}
|
||||
if (!$this->_assumedNextLine('+ ')) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Protocol/Exception.php';
|
||||
throw new Postman_Zend_Mail_Protocol_Exception('cannot send literal string');
|
||||
}
|
||||
$line = $token[1];
|
||||
} else {
|
||||
$line .= ' ' . $token;
|
||||
}
|
||||
}
|
||||
|
||||
if (@fputs($this->_socket, $line . "\r\n") === false) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Protocol/Exception.php';
|
||||
throw new Postman_Zend_Mail_Protocol_Exception('cannot write - connection closed?');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* send a request and get response at once
|
||||
*
|
||||
* @param string $command command as in sendRequest()
|
||||
* @param array $tokens parameters as in sendRequest()
|
||||
* @param bool $dontParse if true unparsed lines are returned instead of tokens
|
||||
* @return mixed response as in readResponse()
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function requestAndResponse($command, $tokens = array(), $dontParse = false)
|
||||
{
|
||||
$this->sendRequest($command, $tokens, $tag);
|
||||
$response = $this->readResponse($tag, $dontParse);
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* escape one or more literals i.e. for sendRequest
|
||||
*
|
||||
* @param string|array $string the literal/-s
|
||||
* @return string|array escape literals, literals with newline ar returned
|
||||
* as array('{size}', 'string');
|
||||
*/
|
||||
public function escapeString($string)
|
||||
{
|
||||
if (func_num_args() < 2) {
|
||||
if (strpos($string, "\n") !== false) {
|
||||
return array('{' . strlen($string) . '}', $string);
|
||||
} else {
|
||||
return '"' . str_replace(array('\\', '"'), array('\\\\', '\\"'), $string) . '"';
|
||||
}
|
||||
}
|
||||
$result = array();
|
||||
foreach (func_get_args() as $string) {
|
||||
$result[] = $this->escapeString($string);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* escape a list with literals or lists
|
||||
*
|
||||
* @param array $list list with literals or lists as PHP array
|
||||
* @return string escaped list for imap
|
||||
*/
|
||||
public function escapeList($list)
|
||||
{
|
||||
$result = array();
|
||||
foreach ($list as $k => $v) {
|
||||
if (!is_array($v)) {
|
||||
// $result[] = $this->escapeString($v);
|
||||
$result[] = $v;
|
||||
continue;
|
||||
}
|
||||
$result[] = $this->escapeList($v);
|
||||
}
|
||||
return '(' . implode(' ', $result) . ')';
|
||||
}
|
||||
|
||||
/**
|
||||
* Login to IMAP server.
|
||||
*
|
||||
* @param string $user username
|
||||
* @param string $password password
|
||||
* @return bool success
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function login($user, $password)
|
||||
{
|
||||
return $this->requestAndResponse('LOGIN', $this->escapeString($user, $password), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* logout of imap server
|
||||
*
|
||||
* @return bool success
|
||||
*/
|
||||
public function logout()
|
||||
{
|
||||
$result = false;
|
||||
if ($this->_socket) {
|
||||
try {
|
||||
$result = $this->requestAndResponse('LOGOUT', array(), true);
|
||||
} catch (Postman_Zend_Mail_Protocol_Exception $e) {
|
||||
// ignoring exception
|
||||
}
|
||||
fclose($this->_socket);
|
||||
$this->_socket = null;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get capabilities from IMAP server
|
||||
*
|
||||
* @return array list of capabilities
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function capability()
|
||||
{
|
||||
$response = $this->requestAndResponse('CAPABILITY');
|
||||
|
||||
if (!$response) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$capabilities = array();
|
||||
foreach ($response as $line) {
|
||||
$capabilities = array_merge($capabilities, $line);
|
||||
}
|
||||
return $capabilities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Examine and select have the same response. The common code for both
|
||||
* is in this method
|
||||
*
|
||||
* @param string $command can be 'EXAMINE' or 'SELECT' and this is used as command
|
||||
* @param string $box which folder to change to or examine
|
||||
* @return bool|array false if error, array with returned information
|
||||
* otherwise (flags, exists, recent, uidvalidity)
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function examineOrSelect($command = 'EXAMINE', $box = 'INBOX')
|
||||
{
|
||||
$this->sendRequest($command, array($this->escapeString($box)), $tag);
|
||||
|
||||
$result = array();
|
||||
while (!$this->readLine($tokens, $tag)) {
|
||||
if ($tokens[0] == 'FLAGS') {
|
||||
array_shift($tokens);
|
||||
$result['flags'] = $tokens;
|
||||
continue;
|
||||
}
|
||||
switch ($tokens[1]) {
|
||||
case 'EXISTS':
|
||||
case 'RECENT':
|
||||
$result[strtolower($tokens[1])] = $tokens[0];
|
||||
break;
|
||||
case '[UIDVALIDITY':
|
||||
$result['uidvalidity'] = (int)$tokens[2];
|
||||
break;
|
||||
default:
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
if ($tokens[0] != 'OK') {
|
||||
return false;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* change folder
|
||||
*
|
||||
* @param string $box change to this folder
|
||||
* @return bool|array see examineOrselect()
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function select($box = 'INBOX')
|
||||
{
|
||||
return $this->examineOrSelect('SELECT', $box);
|
||||
}
|
||||
|
||||
/**
|
||||
* examine folder
|
||||
*
|
||||
* @param string $box examine this folder
|
||||
* @return bool|array see examineOrselect()
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function examine($box = 'INBOX')
|
||||
{
|
||||
return $this->examineOrSelect('EXAMINE', $box);
|
||||
}
|
||||
|
||||
/**
|
||||
* fetch one or more items of one or more messages
|
||||
*
|
||||
* @param string|array $items items to fetch from message(s) as string (if only one item)
|
||||
* or array of strings
|
||||
* @param int $from message for items or start message if $to !== null
|
||||
* @param int|null $to if null only one message ($from) is fetched, else it's the
|
||||
* last message, INF means last message avaible
|
||||
* @return string|array if only one item of one message is fetched it's returned as string
|
||||
* if items of one message are fetched it's returned as (name => value)
|
||||
* if one items of messages are fetched it's returned as (msgno => value)
|
||||
* if items of messages are fetchted it's returned as (msgno => (name => value))
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function fetch($items, $from, $to = null)
|
||||
{
|
||||
if (is_array($from)) {
|
||||
$set = implode(',', $from);
|
||||
} else if ($to === null) {
|
||||
$set = (int)$from;
|
||||
} else if ($to === INF) {
|
||||
$set = (int)$from . ':*';
|
||||
} else {
|
||||
$set = (int)$from . ':' . (int)$to;
|
||||
}
|
||||
|
||||
$items = (array)$items;
|
||||
$itemList = $this->escapeList($items);
|
||||
|
||||
$this->sendRequest('FETCH', array($set, $itemList), $tag);
|
||||
|
||||
$result = array();
|
||||
while (!$this->readLine($tokens, $tag)) {
|
||||
// ignore other responses
|
||||
if ($tokens[1] != 'FETCH') {
|
||||
continue;
|
||||
}
|
||||
// ignore other messages
|
||||
if ($to === null && !is_array($from) && $tokens[0] != $from) {
|
||||
continue;
|
||||
}
|
||||
// if we only want one item we return that one directly
|
||||
if (count($items) == 1) {
|
||||
if ($tokens[2][0] == $items[0]) {
|
||||
$data = $tokens[2][1];
|
||||
} else {
|
||||
// maybe the server send an other field we didn't wanted
|
||||
$count = count($tokens[2]);
|
||||
// we start with 2, because 0 was already checked
|
||||
for ($i = 2; $i < $count; $i += 2) {
|
||||
if ($tokens[2][$i] != $items[0]) {
|
||||
continue;
|
||||
}
|
||||
$data = $tokens[2][$i + 1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$data = array();
|
||||
while (key($tokens[2]) !== null) {
|
||||
$data[current($tokens[2])] = next($tokens[2]);
|
||||
next($tokens[2]);
|
||||
}
|
||||
}
|
||||
// if we want only one message we can ignore everything else and just return
|
||||
if ($to === null && !is_array($from) && $tokens[0] == $from) {
|
||||
// we still need to read all lines
|
||||
while (!$this->readLine($tokens, $tag));
|
||||
return $data;
|
||||
}
|
||||
$result[$tokens[0]] = $data;
|
||||
}
|
||||
|
||||
if ($to === null && !is_array($from)) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Protocol/Exception.php';
|
||||
throw new Postman_Zend_Mail_Protocol_Exception('the single id was not found in response');
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* get mailbox list
|
||||
*
|
||||
* this method can't be named after the IMAP command 'LIST', as list is a reserved keyword
|
||||
*
|
||||
* @param string $reference mailbox reference for list
|
||||
* @param string $mailbox mailbox name match with wildcards
|
||||
* @return array mailboxes that matched $mailbox as array(globalName => array('delim' => .., 'flags' => ..))
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function listMailbox($reference = '', $mailbox = '*')
|
||||
{
|
||||
$result = array();
|
||||
$list = $this->requestAndResponse('LIST', $this->escapeString($reference, $mailbox));
|
||||
if (!$list || $list === true) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
foreach ($list as $item) {
|
||||
if (count($item) != 4 || $item[0] != 'LIST') {
|
||||
continue;
|
||||
}
|
||||
$result[$item[3]] = array('delim' => $item[2], 'flags' => $item[1]);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* set flags
|
||||
*
|
||||
* @param array $flags flags to set, add or remove - see $mode
|
||||
* @param int $from message for items or start message if $to !== null
|
||||
* @param int|null $to if null only one message ($from) is fetched, else it's the
|
||||
* last message, INF means last message avaible
|
||||
* @param string|null $mode '+' to add flags, '-' to remove flags, everything else sets the flags as given
|
||||
* @param bool $silent if false the return values are the new flags for the wanted messages
|
||||
* @return bool|array new flags if $silent is false, else true or false depending on success
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function store(array $flags, $from, $to = null, $mode = null, $silent = true)
|
||||
{
|
||||
$item = 'FLAGS';
|
||||
if ($mode == '+' || $mode == '-') {
|
||||
$item = $mode . $item;
|
||||
}
|
||||
if ($silent) {
|
||||
$item .= '.SILENT';
|
||||
}
|
||||
|
||||
$flags = $this->escapeList($flags);
|
||||
$set = (int)$from;
|
||||
if ($to != null) {
|
||||
$set .= ':' . ($to == INF ? '*' : (int)$to);
|
||||
}
|
||||
|
||||
$result = $this->requestAndResponse('STORE', array($set, $item, $flags), $silent);
|
||||
|
||||
if ($silent) {
|
||||
return $result ? true : false;
|
||||
}
|
||||
|
||||
$tokens = $result;
|
||||
$result = array();
|
||||
foreach ($tokens as $token) {
|
||||
if ($token[1] != 'FETCH' || $token[2][0] != 'FLAGS') {
|
||||
continue;
|
||||
}
|
||||
$result[$token[0]] = $token[2][1];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* append a new message to given folder
|
||||
*
|
||||
* @param string $folder name of target folder
|
||||
* @param string $message full message content
|
||||
* @param array $flags flags for new message
|
||||
* @param string $date date for new message
|
||||
* @return bool success
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function append($folder, $message, $flags = null, $date = null)
|
||||
{
|
||||
$tokens = array();
|
||||
$tokens[] = $this->escapeString($folder);
|
||||
if ($flags !== null) {
|
||||
$tokens[] = $this->escapeList($flags);
|
||||
}
|
||||
if ($date !== null) {
|
||||
$tokens[] = $this->escapeString($date);
|
||||
}
|
||||
$tokens[] = $this->escapeString($message);
|
||||
|
||||
return $this->requestAndResponse('APPEND', $tokens, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* copy message set from current folder to other folder
|
||||
*
|
||||
* @param string $folder destination folder
|
||||
* @param int|null $to if null only one message ($from) is fetched, else it's the
|
||||
* last message, INF means last message avaible
|
||||
* @return bool success
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function copy($folder, $from, $to = null)
|
||||
{
|
||||
$set = (int)$from;
|
||||
if ($to != null) {
|
||||
$set .= ':' . ($to == INF ? '*' : (int)$to);
|
||||
}
|
||||
|
||||
return $this->requestAndResponse('COPY', array($set, $this->escapeString($folder)), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* create a new folder (and parent folders if needed)
|
||||
*
|
||||
* @param string $folder folder name
|
||||
* @return bool success
|
||||
*/
|
||||
public function create($folder)
|
||||
{
|
||||
return $this->requestAndResponse('CREATE', array($this->escapeString($folder)), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* rename an existing folder
|
||||
*
|
||||
* @param string $old old name
|
||||
* @param string $new new name
|
||||
* @return bool success
|
||||
*/
|
||||
public function rename($old, $new)
|
||||
{
|
||||
return $this->requestAndResponse('RENAME', $this->escapeString($old, $new), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* remove a folder
|
||||
*
|
||||
* @param string $folder folder name
|
||||
* @return bool success
|
||||
*/
|
||||
public function delete($folder)
|
||||
{
|
||||
return $this->requestAndResponse('DELETE', array($this->escapeString($folder)), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* permanently remove messages
|
||||
*
|
||||
* @return bool success
|
||||
*/
|
||||
public function expunge()
|
||||
{
|
||||
// TODO: parse response?
|
||||
return $this->requestAndResponse('EXPUNGE');
|
||||
}
|
||||
|
||||
/**
|
||||
* send noop
|
||||
*
|
||||
* @return bool success
|
||||
*/
|
||||
public function noop()
|
||||
{
|
||||
// TODO: parse response
|
||||
return $this->requestAndResponse('NOOP');
|
||||
}
|
||||
|
||||
/**
|
||||
* do a search request
|
||||
*
|
||||
* This method is currently marked as internal as the API might change and is not
|
||||
* safe if you don't take precautions.
|
||||
*
|
||||
* @internal
|
||||
* @return array message ids
|
||||
*/
|
||||
public function search(array $params)
|
||||
{
|
||||
$response = $this->requestAndResponse('SEARCH', $params);
|
||||
if (!$response) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
foreach ($response as $ids) {
|
||||
if ($ids[0] == 'SEARCH') {
|
||||
array_shift($ids);
|
||||
return $ids;
|
||||
}
|
||||
}
|
||||
return array();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,472 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Protocol
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Protocol
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Postman_Zend_Mail_Protocol_Pop3
|
||||
{
|
||||
/**
|
||||
* Default timeout in seconds for initiating session
|
||||
*/
|
||||
const TIMEOUT_CONNECTION = 30;
|
||||
|
||||
/**
|
||||
* saves if server supports top
|
||||
* @var null|bool
|
||||
*/
|
||||
public $hasTop = null;
|
||||
|
||||
/**
|
||||
* socket to pop3
|
||||
* @var null|resource
|
||||
*/
|
||||
protected $_socket;
|
||||
|
||||
/**
|
||||
* greeting timestamp for apop
|
||||
* @var null|string
|
||||
*/
|
||||
protected $_timestamp;
|
||||
|
||||
|
||||
/**
|
||||
* Public constructor
|
||||
*
|
||||
* @param string $host hostname or IP address of POP3 server, if given connect() is called
|
||||
* @param int|null $port port of POP3 server, null for default (110 or 995 for ssl)
|
||||
* @param bool|string $ssl use ssl? 'SSL', 'TLS' or false
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function __construct($host = '', $port = null, $ssl = false)
|
||||
{
|
||||
if ($host) {
|
||||
$this->connect($host, $port, $ssl);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Public destructor
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
$this->logout();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Open connection to POP3 server
|
||||
*
|
||||
* @param string $host hostname or IP address of POP3 server
|
||||
* @param int|null $port of POP3 server, default is 110 (995 for ssl)
|
||||
* @param string|bool $ssl use 'SSL', 'TLS' or false
|
||||
* @return string welcome message
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function connect($host, $port = null, $ssl = false)
|
||||
{
|
||||
if ($ssl == 'SSL') {
|
||||
$host = 'ssl://' . $host;
|
||||
}
|
||||
|
||||
if ($port === null) {
|
||||
$port = $ssl == 'SSL' ? 995 : 110;
|
||||
}
|
||||
|
||||
$errno = 0;
|
||||
$errstr = '';
|
||||
$this->_socket = @fsockopen($host, $port, $errno, $errstr, self::TIMEOUT_CONNECTION);
|
||||
if (!$this->_socket) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Protocol/Exception.php';
|
||||
throw new Postman_Zend_Mail_Protocol_Exception('cannot connect to host; error = ' . $errstr .
|
||||
' (errno = ' . $errno . ' )');
|
||||
}
|
||||
|
||||
$welcome = $this->readResponse();
|
||||
|
||||
strtok($welcome, '<');
|
||||
$this->_timestamp = strtok('>');
|
||||
if (!strpos($this->_timestamp, '@')) {
|
||||
$this->_timestamp = null;
|
||||
} else {
|
||||
$this->_timestamp = '<' . $this->_timestamp . '>';
|
||||
}
|
||||
|
||||
if ($ssl === 'TLS') {
|
||||
$this->request('STLS');
|
||||
$result = stream_socket_enable_crypto($this->_socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
|
||||
if (!$result) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Protocol/Exception.php';
|
||||
throw new Postman_Zend_Mail_Protocol_Exception('cannot enable TLS');
|
||||
}
|
||||
}
|
||||
|
||||
return $welcome;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send a request
|
||||
*
|
||||
* @param string $request your request without newline
|
||||
* @return null
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function sendRequest($request)
|
||||
{
|
||||
$result = @fputs($this->_socket, $request . "\r\n");
|
||||
if (!$result) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Protocol/Exception.php';
|
||||
throw new Postman_Zend_Mail_Protocol_Exception('send failed - connection closed?');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* read a response
|
||||
*
|
||||
* @param boolean $multiline response has multiple lines and should be read until "<nl>.<nl>"
|
||||
* @return string response
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function readResponse($multiline = false)
|
||||
{
|
||||
$result = @fgets($this->_socket);
|
||||
if (!is_string($result)) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Protocol/Exception.php';
|
||||
throw new Postman_Zend_Mail_Protocol_Exception('read failed - connection closed?');
|
||||
}
|
||||
|
||||
$result = trim($result);
|
||||
if (strpos($result, ' ')) {
|
||||
list($status, $message) = explode(' ', $result, 2);
|
||||
} else {
|
||||
$status = $result;
|
||||
$message = '';
|
||||
}
|
||||
|
||||
if ($status != '+OK') {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Protocol/Exception.php';
|
||||
throw new Postman_Zend_Mail_Protocol_Exception('last request failed');
|
||||
}
|
||||
|
||||
if ($multiline) {
|
||||
$message = '';
|
||||
$line = fgets($this->_socket);
|
||||
while ($line && rtrim($line, "\r\n") != '.') {
|
||||
if ($line[0] == '.') {
|
||||
$line = substr($line, 1);
|
||||
}
|
||||
$message .= $line;
|
||||
$line = fgets($this->_socket);
|
||||
};
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send request and get resposne
|
||||
*
|
||||
* @see sendRequest(), readResponse()
|
||||
*
|
||||
* @param string $request request
|
||||
* @param bool $multiline multiline response?
|
||||
* @return string result from readResponse()
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function request($request, $multiline = false)
|
||||
{
|
||||
$this->sendRequest($request);
|
||||
return $this->readResponse($multiline);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* End communication with POP3 server (also closes socket)
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function logout()
|
||||
{
|
||||
if (!$this->_socket) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->request('QUIT');
|
||||
} catch (Postman_Zend_Mail_Protocol_Exception $e) {
|
||||
// ignore error - we're closing the socket anyway
|
||||
}
|
||||
|
||||
fclose($this->_socket);
|
||||
$this->_socket = null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get capabilities from POP3 server
|
||||
*
|
||||
* @return array list of capabilities
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function capa()
|
||||
{
|
||||
$result = $this->request('CAPA', true);
|
||||
return explode("\n", $result);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Login to POP3 server. Can use APOP
|
||||
*
|
||||
* @param string $user username
|
||||
* @param string $password password
|
||||
* @param bool $try_apop should APOP be tried?
|
||||
* @return void
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function login($user, $password, $tryApop = true)
|
||||
{
|
||||
if ($tryApop && $this->_timestamp) {
|
||||
try {
|
||||
$this->request("APOP $user " . md5($this->_timestamp . $password));
|
||||
return;
|
||||
} catch (Postman_Zend_Mail_Protocol_Exception $e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
$result = $this->request("USER $user");
|
||||
$result = $this->request("PASS $password");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make STAT call for message count and size sum
|
||||
*
|
||||
* @param int $messages out parameter with count of messages
|
||||
* @param int $octets out parameter with size in octects of messages
|
||||
* @return void
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function status(&$messages, &$octets)
|
||||
{
|
||||
$messages = 0;
|
||||
$octets = 0;
|
||||
$result = $this->request('STAT');
|
||||
|
||||
list($messages, $octets) = explode(' ', $result);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make LIST call for size of message(s)
|
||||
*
|
||||
* @param int|null $msgno number of message, null for all
|
||||
* @return int|array size of given message or list with array(num => size)
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function getList($msgno = null)
|
||||
{
|
||||
if ($msgno !== null) {
|
||||
$result = $this->request("LIST $msgno");
|
||||
|
||||
list(, $result) = explode(' ', $result);
|
||||
return (int)$result;
|
||||
}
|
||||
|
||||
$result = $this->request('LIST', true);
|
||||
$messages = array();
|
||||
$line = strtok($result, "\n");
|
||||
while ($line) {
|
||||
list($no, $size) = explode(' ', trim($line));
|
||||
$messages[(int)$no] = (int)$size;
|
||||
$line = strtok("\n");
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make UIDL call for getting a uniqueid
|
||||
*
|
||||
* @param int|null $msgno number of message, null for all
|
||||
* @return string|array uniqueid of message or list with array(num => uniqueid)
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function uniqueid($msgno = null)
|
||||
{
|
||||
if ($msgno !== null) {
|
||||
$result = $this->request("UIDL $msgno");
|
||||
|
||||
list(, $result) = explode(' ', $result);
|
||||
return $result;
|
||||
}
|
||||
|
||||
$result = $this->request('UIDL', true);
|
||||
|
||||
$result = explode("\n", $result);
|
||||
$messages = array();
|
||||
foreach ($result as $line) {
|
||||
if (!$line) {
|
||||
continue;
|
||||
}
|
||||
list($no, $id) = explode(' ', trim($line), 2);
|
||||
$messages[(int)$no] = $id;
|
||||
}
|
||||
|
||||
return $messages;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make TOP call for getting headers and maybe some body lines
|
||||
* This method also sets hasTop - before it it's not known if top is supported
|
||||
*
|
||||
* The fallback makes normale RETR call, which retrieves the whole message. Additional
|
||||
* lines are not removed.
|
||||
*
|
||||
* @param int $msgno number of message
|
||||
* @param int $lines number of wanted body lines (empty line is inserted after header lines)
|
||||
* @param bool $fallback fallback with full retrieve if top is not supported
|
||||
* @return string message headers with wanted body lines
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function top($msgno, $lines = 0, $fallback = false)
|
||||
{
|
||||
if ($this->hasTop === false) {
|
||||
if ($fallback) {
|
||||
return $this->retrieve($msgno);
|
||||
} else {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Protocol/Exception.php';
|
||||
throw new Postman_Zend_Mail_Protocol_Exception('top not supported and no fallback wanted');
|
||||
}
|
||||
}
|
||||
$this->hasTop = true;
|
||||
|
||||
$lines = (!$lines || $lines < 1) ? 0 : (int)$lines;
|
||||
|
||||
try {
|
||||
$result = $this->request("TOP $msgno $lines", true);
|
||||
} catch (Postman_Zend_Mail_Protocol_Exception $e) {
|
||||
$this->hasTop = false;
|
||||
if ($fallback) {
|
||||
$result = $this->retrieve($msgno);
|
||||
} else {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make a RETR call for retrieving a full message with headers and body
|
||||
*
|
||||
* @deprecated since 1.1.0; this method has a typo - please use retrieve()
|
||||
* @param int $msgno message number
|
||||
* @return string message
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function retrive($msgno)
|
||||
{
|
||||
return $this->retrieve($msgno);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make a RETR call for retrieving a full message with headers and body
|
||||
*
|
||||
* @param int $msgno message number
|
||||
* @return string message
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function retrieve($msgno)
|
||||
{
|
||||
$result = $this->request("RETR $msgno", true);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make a NOOP call, maybe needed for keeping the server happy
|
||||
*
|
||||
* @return null
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function noop()
|
||||
{
|
||||
$this->request('NOOP');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make a DELE count to remove a message
|
||||
*
|
||||
* @return null
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function delete($msgno)
|
||||
{
|
||||
$this->request("DELE $msgno");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Make RSET call, which rollbacks delete requests
|
||||
*
|
||||
* @return null
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function undelete()
|
||||
{
|
||||
$this->request('RSET');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,467 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Protocol
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mime
|
||||
*/
|
||||
// require_once 'Zend/Mime.php';
|
||||
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Abstract
|
||||
*/
|
||||
// require_once 'Zend/Mail/Protocol/Abstract.php';
|
||||
|
||||
|
||||
/**
|
||||
* Smtp implementation of Postman_Zend_Mail_Protocol_Abstract
|
||||
*
|
||||
* Minimum implementation according to RFC2821: EHLO, MAIL FROM, RCPT TO, DATA, RSET, NOOP, QUIT
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Protocol
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Postman_Zend_Mail_Protocol_Smtp extends Postman_Zend_Mail_Protocol_Abstract
|
||||
{
|
||||
/**
|
||||
* The transport method for the socket
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_transport = 'tcp';
|
||||
|
||||
|
||||
/**
|
||||
* Indicates that a session is requested to be secure
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_secure;
|
||||
|
||||
|
||||
/**
|
||||
* Indicates an smtp session has been started by the HELO command
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $_sess = false;
|
||||
|
||||
|
||||
/**
|
||||
* Indicates the HELO command has been issues
|
||||
*
|
||||
* @var unknown_type
|
||||
*/
|
||||
protected $_helo = false;
|
||||
|
||||
|
||||
/**
|
||||
* Indicates an smtp AUTH has been issued and authenticated
|
||||
*
|
||||
* @var unknown_type
|
||||
*/
|
||||
protected $_auth = false;
|
||||
|
||||
|
||||
/**
|
||||
* Indicates a MAIL command has been issued
|
||||
*
|
||||
* @var unknown_type
|
||||
*/
|
||||
protected $_mail = false;
|
||||
|
||||
|
||||
/**
|
||||
* Indicates one or more RCTP commands have been issued
|
||||
*
|
||||
* @var unknown_type
|
||||
*/
|
||||
protected $_rcpt = false;
|
||||
|
||||
|
||||
/**
|
||||
* Indicates that DATA has been issued and sent
|
||||
*
|
||||
* @var unknown_type
|
||||
*/
|
||||
protected $_data = null;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $host
|
||||
* @param integer $port
|
||||
* @param array $config
|
||||
* @return void
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function __construct($host = '127.0.0.1', $port = null, array $config = array())
|
||||
{
|
||||
if (isset($config['ssl'])) {
|
||||
switch (strtolower($config['ssl'])) {
|
||||
case 'tls':
|
||||
$this->_secure = 'tls';
|
||||
break;
|
||||
|
||||
case 'ssl':
|
||||
$this->_transport = 'ssl';
|
||||
$this->_secure = 'ssl';
|
||||
if ($port == null) {
|
||||
$port = 465;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
// require_once 'Zend/Mail/Protocol/Exception.php';
|
||||
throw new Postman_Zend_Mail_Protocol_Exception($config['ssl'] . ' is unsupported SSL type');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If no port has been specified then check the master PHP ini file. Defaults to 25 if the ini setting is null.
|
||||
if ($port == null) {
|
||||
if (($port = ini_get('smtp_port')) == '') {
|
||||
$port = 25;
|
||||
}
|
||||
}
|
||||
|
||||
parent::__construct($host, $port);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Connect to the server with the parameters given in the constructor.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function connect()
|
||||
{
|
||||
return $this->_connect($this->_transport . '://' . $this->_host . ':'. $this->_port);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initiate HELO/EHLO sequence and set flag to indicate valid smtp session
|
||||
*
|
||||
* @param string $host The client hostname or IP address (default: 127.0.0.1)
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
* @return void
|
||||
*/
|
||||
public function helo($host = '127.0.0.1')
|
||||
{
|
||||
// Respect RFC 2821 and disallow HELO attempts if session is already initiated.
|
||||
if ($this->_sess === true) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
// require_once 'Zend/Mail/Protocol/Exception.php';
|
||||
throw new Postman_Zend_Mail_Protocol_Exception('Cannot issue HELO to existing session');
|
||||
}
|
||||
|
||||
// Validate client hostname
|
||||
if (!$this->_validHost->isValid($host)) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
// require_once 'Zend/Mail/Protocol/Exception.php';
|
||||
throw new Postman_Zend_Mail_Protocol_Exception(join(', ', $this->_validHost->getMessages()));
|
||||
}
|
||||
|
||||
// Initiate helo sequence
|
||||
$this->_expect(220, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
|
||||
$this->_ehlo($host);
|
||||
|
||||
// If a TLS session is required, commence negotiation
|
||||
if ($this->_secure == 'tls') {
|
||||
$this->_send('STARTTLS');
|
||||
$this->_expect(220, 180);
|
||||
|
||||
stream_context_set_option($this->_socket, 'ssl', 'verify_peer', false);
|
||||
stream_context_set_option($this->_socket, 'ssl', 'verify_peer_name', false);
|
||||
stream_context_set_option($this->_socket, 'ssl', 'allow_self_signed', true);
|
||||
|
||||
$crypto_method = STREAM_CRYPTO_METHOD_TLS_CLIENT;
|
||||
|
||||
$curl = curl_version();
|
||||
preg_match('/.*\/(\d*\.\d*\.\d*)[a-z]?/', $curl['ssl_version'], $ver_match );
|
||||
$tlsv1_2_installed = ! empty( $ver_match[1] ) ? $ver_match[1] >= '1.0.1' : true;
|
||||
|
||||
if ( $this->_host == 'smtp.office365.com' && ! $tlsv1_2_installed ) {
|
||||
|
||||
$error = sprintf( 'Office365 SMTP servie require TLS v1.2 and OpenSSL version 1.0.1 or greater, your current OpenSSL version is: %s.
|
||||
You need to contact your web hosting support for help.', $ver_match[1] );
|
||||
|
||||
throw new Postman_Zend_Mail_Protocol_Exception( $error );
|
||||
}
|
||||
|
||||
if ( defined('STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT') ) {
|
||||
$crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
|
||||
$crypto_method |= STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
|
||||
}
|
||||
|
||||
if (!stream_socket_enable_crypto($this->_socket, true, $crypto_method)) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
// require_once 'Zend/Mail/Protocol/Exception.php';
|
||||
throw new Postman_Zend_Mail_Protocol_Exception('Unable to connect via TLS');
|
||||
}
|
||||
$this->_ehlo($host);
|
||||
}
|
||||
|
||||
$this->_startSession();
|
||||
$this->auth();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send EHLO or HELO depending on capabilities of smtp host
|
||||
*
|
||||
* @param string $host The client hostname or IP address (default: 127.0.0.1)
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
* @return void
|
||||
*/
|
||||
protected function _ehlo($host)
|
||||
{
|
||||
// Support for older, less-compliant remote servers. Tries multiple attempts of EHLO or HELO.
|
||||
try {
|
||||
$this->_send('EHLO ' . $host);
|
||||
$this->_expect(250, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
|
||||
} catch (Postman_Zend_Mail_Protocol_Exception $e) {
|
||||
$this->_send('HELO ' . $host);
|
||||
$this->_expect(250, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
|
||||
} catch (Postman_Zend_Mail_Protocol_Exception $e) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Issues MAIL command
|
||||
*
|
||||
* @param string $from Sender mailbox
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
* @return void
|
||||
*/
|
||||
public function mail($from)
|
||||
{
|
||||
if ($this->_sess !== true) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
// require_once 'Zend/Mail/Protocol/Exception.php';
|
||||
throw new Postman_Zend_Mail_Protocol_Exception('A valid session has not been started');
|
||||
}
|
||||
|
||||
$this->_send('MAIL FROM:<' . $from . '>');
|
||||
$this->_expect(250, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
|
||||
|
||||
// Set mail to true, clear recipients and any existing data flags as per 4.1.1.2 of RFC 2821
|
||||
$this->_mail = true;
|
||||
$this->_rcpt = false;
|
||||
$this->_data = false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Issues RCPT command
|
||||
*
|
||||
* @param string $to Receiver(s) mailbox
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
* @return void
|
||||
*/
|
||||
public function rcpt($to)
|
||||
{
|
||||
if ($this->_mail !== true) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
// require_once 'Zend/Mail/Protocol/Exception.php';
|
||||
throw new Postman_Zend_Mail_Protocol_Exception('No sender reverse path has been supplied');
|
||||
}
|
||||
|
||||
// Set rcpt to true, as per 4.1.1.3 of RFC 2821
|
||||
$this->_send('RCPT TO:<' . $to . '>');
|
||||
$this->_expect(array(250, 251), 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
|
||||
$this->_rcpt = true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Issues DATA command
|
||||
*
|
||||
* @param string $data
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
* @return void
|
||||
*/
|
||||
public function data($data)
|
||||
{
|
||||
// Ensure recipients have been set
|
||||
if ($this->_rcpt !== true) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
// require_once 'Zend/Mail/Protocol/Exception.php';
|
||||
throw new Postman_Zend_Mail_Protocol_Exception('No recipient forward path has been supplied');
|
||||
}
|
||||
|
||||
$this->_send('DATA');
|
||||
$this->_expect(354, 120); // Timeout set for 2 minutes as per RFC 2821 4.5.3.2
|
||||
|
||||
foreach (explode(Postman_Zend_Mime::LINEEND, $data) as $line) {
|
||||
if (strpos($line, '.') === 0) {
|
||||
// Escape lines prefixed with a '.'
|
||||
$line = '.' . $line;
|
||||
}
|
||||
$this->_send($line);
|
||||
}
|
||||
|
||||
$this->_send('.');
|
||||
$this->_expect(250, 600); // Timeout set for 10 minutes as per RFC 2821 4.5.3.2
|
||||
$this->_data = true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Issues the RSET command and validates answer
|
||||
*
|
||||
* Can be used to restore a clean smtp communication state when a transaction has been cancelled or commencing a new transaction.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function rset()
|
||||
{
|
||||
$this->_send('RSET');
|
||||
// MS ESMTP doesn't follow RFC, see [ZF-1377]
|
||||
$this->_expect(array(250, 220));
|
||||
|
||||
$this->_mail = false;
|
||||
$this->_rcpt = false;
|
||||
$this->_data = false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Issues the NOOP command and validates answer
|
||||
*
|
||||
* Not used by Postman_Zend_Mail, could be used to keep a connection alive or check if it is still open.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function noop()
|
||||
{
|
||||
$this->_send('NOOP');
|
||||
$this->_expect(250, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Issues the VRFY command and validates answer
|
||||
*
|
||||
* Not used by Postman_Zend_Mail.
|
||||
*
|
||||
* @param string $user User Name or eMail to verify
|
||||
* @return void
|
||||
*/
|
||||
public function vrfy($user)
|
||||
{
|
||||
$this->_send('VRFY ' . $user);
|
||||
$this->_expect(array(250, 251, 252), 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Issues the QUIT command and clears the current session
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function quit()
|
||||
{
|
||||
if ($this->_sess) {
|
||||
$this->_send('QUIT');
|
||||
$this->_expect(221, 300); // Timeout set for 5 minutes as per RFC 2821 4.5.3.2
|
||||
$this->_stopSession();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Default authentication method
|
||||
*
|
||||
* This default method is implemented by AUTH adapters to properly authenticate to a remote host.
|
||||
*
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
* @return void
|
||||
*/
|
||||
public function auth()
|
||||
{
|
||||
if ($this->_auth === true) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
// require_once 'Zend/Mail/Protocol/Exception.php';
|
||||
throw new Postman_Zend_Mail_Protocol_Exception('Already authenticated for this session');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Closes connection
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function disconnect()
|
||||
{
|
||||
$this->_disconnect();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Start mail session
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function _startSession()
|
||||
{
|
||||
$this->_sess = true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Stop mail session
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function _stopSession()
|
||||
{
|
||||
$this->_sess = false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Protocol
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Smtp
|
||||
*/
|
||||
// require_once 'Zend/Mail/Protocol/Smtp.php';
|
||||
|
||||
|
||||
/**
|
||||
* Performs CRAM-MD5 authentication
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Protocol
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Postman_Zend_Mail_Protocol_Smtp_Auth_Crammd5 extends Postman_Zend_Mail_Protocol_Smtp
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $host (Default: 127.0.0.1)
|
||||
* @param int $port (Default: null)
|
||||
* @param array $config Auth-specific parameters
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($host = '127.0.0.1', $port = null, $config = null)
|
||||
{
|
||||
if (is_array($config)) {
|
||||
if (isset($config['username'])) {
|
||||
$this->_username = $config['username'];
|
||||
}
|
||||
if (isset($config['password'])) {
|
||||
$this->_password = $config['password'];
|
||||
}
|
||||
}
|
||||
|
||||
parent::__construct($host, $port, $config);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @todo Perform CRAM-MD5 authentication with supplied credentials
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function auth()
|
||||
{
|
||||
// Ensure AUTH has not already been initiated.
|
||||
parent::auth();
|
||||
|
||||
$this->_send('AUTH CRAM-MD5');
|
||||
$challenge = $this->_expect(334);
|
||||
$challenge = base64_decode($challenge);
|
||||
$digest = $this->_hmacMd5($this->_password, $challenge);
|
||||
$this->_send(base64_encode($this->_username . ' ' . $digest));
|
||||
$this->_expect(235);
|
||||
$this->_auth = true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prepare CRAM-MD5 response to server's ticket
|
||||
*
|
||||
* @param string $key Challenge key (usually password)
|
||||
* @param string $data Challenge data
|
||||
* @param string $block Length of blocks
|
||||
* @return string
|
||||
*/
|
||||
protected function _hmacMd5($key, $data, $block = 64)
|
||||
{
|
||||
if (strlen($key) > 64) {
|
||||
$key = pack('H32', md5($key));
|
||||
} elseif (strlen($key) < 64) {
|
||||
$key = str_pad($key, $block, "\0");
|
||||
}
|
||||
|
||||
$k_ipad = substr($key, 0, 64) ^ str_repeat(chr(0x36), 64);
|
||||
$k_opad = substr($key, 0, 64) ^ str_repeat(chr(0x5C), 64);
|
||||
|
||||
$inner = pack('H32', md5($k_ipad . $data));
|
||||
$digest = md5($k_opad . $inner);
|
||||
|
||||
return $digest;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Protocol
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Smtp
|
||||
*/
|
||||
// require_once 'Zend/Mail/Protocol/Smtp.php';
|
||||
|
||||
|
||||
/**
|
||||
* Performs LOGIN authentication
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Protocol
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Postman_Zend_Mail_Protocol_Smtp_Auth_Login extends Postman_Zend_Mail_Protocol_Smtp
|
||||
{
|
||||
/**
|
||||
* LOGIN username
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_username;
|
||||
|
||||
|
||||
/**
|
||||
* LOGIN password
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_password;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $host (Default: 127.0.0.1)
|
||||
* @param int $port (Default: null)
|
||||
* @param array $config Auth-specific parameters
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($host = '127.0.0.1', $port = null, $config = null)
|
||||
{
|
||||
if (is_array($config)) {
|
||||
if (isset($config['username'])) {
|
||||
$this->_username = $config['username'];
|
||||
}
|
||||
if (isset($config['password'])) {
|
||||
$this->_password = $config['password'];
|
||||
}
|
||||
}
|
||||
|
||||
parent::__construct($host, $port, $config);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Perform LOGIN authentication with supplied credentials
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function auth()
|
||||
{
|
||||
// Ensure AUTH has not already been initiated.
|
||||
parent::auth();
|
||||
|
||||
$this->_send('AUTH LOGIN');
|
||||
$this->_expect(334);
|
||||
$this->_send(base64_encode($this->_username));
|
||||
$this->_expect(334);
|
||||
$this->_send(base64_encode($this->_password));
|
||||
$this->_expect(235);
|
||||
$this->_auth = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Protocol
|
||||
* @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id: Login.php 24593 2012-01-05 20:35:02Z matthew $
|
||||
*/
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Smtp
|
||||
*/
|
||||
|
||||
/**
|
||||
* Performs Oauth2 authentication
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Protocol
|
||||
* @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Postman_Zend_Mail_Protocol_Smtp_Auth_Oauth2 extends Postman_Zend_Mail_Protocol_Smtp
|
||||
{
|
||||
/**
|
||||
* LOGIN xoauth2 request
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_xoauth2_request;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $host (Default: 127.0.0.1)
|
||||
* @param int $port (Default: null)
|
||||
* @param array $config Auth-specific parameters
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($host = '127.0.0.1', $port = null, $config = null)
|
||||
{
|
||||
if (is_array($config)) {
|
||||
if (isset($config['xoauth2_request'])) {
|
||||
$this->_xoauth2_request = $config['xoauth2_request'];
|
||||
}
|
||||
}
|
||||
|
||||
parent::__construct($host, $port, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform LOGIN authentication with supplied credentials
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function auth()
|
||||
{
|
||||
// Ensure AUTH has not already been initiated.
|
||||
parent::auth();
|
||||
|
||||
$this->_send('AUTH XOAUTH2 '.$this->_xoauth2_request);
|
||||
$this->_expect(235);
|
||||
$this->_auth = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Protocol
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Smtp
|
||||
*/
|
||||
// require_once 'Zend/Mail/Protocol/Smtp.php';
|
||||
|
||||
|
||||
/**
|
||||
* Performs PLAIN authentication
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Protocol
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Postman_Zend_Mail_Protocol_Smtp_Auth_Plain extends Postman_Zend_Mail_Protocol_Smtp
|
||||
{
|
||||
/**
|
||||
* PLAIN username
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_username;
|
||||
|
||||
|
||||
/**
|
||||
* PLAIN password
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_password;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $host (Default: 127.0.0.1)
|
||||
* @param int $port (Default: null)
|
||||
* @param array $config Auth-specific parameters
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($host = '127.0.0.1', $port = null, $config = null)
|
||||
{
|
||||
if (is_array($config)) {
|
||||
if (isset($config['username'])) {
|
||||
$this->_username = $config['username'];
|
||||
}
|
||||
if (isset($config['password'])) {
|
||||
$this->_password = $config['password'];
|
||||
}
|
||||
}
|
||||
|
||||
parent::__construct($host, $port, $config);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Perform PLAIN authentication with supplied credentials
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function auth()
|
||||
{
|
||||
// Ensure AUTH has not already been initiated.
|
||||
parent::auth();
|
||||
|
||||
$this->_send('AUTH PLAIN');
|
||||
$this->_expect(334);
|
||||
$this->_send(base64_encode("\0" . $this->_username . "\0" . $this->_password));
|
||||
$this->_expect(235);
|
||||
$this->_auth = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Postman_Zend_Mail_Storage
|
||||
{
|
||||
// maildir and IMAP flags, using IMAP names, where possible to be able to distinguish between IMAP
|
||||
// system flags and other flags
|
||||
const FLAG_PASSED = 'Passed';
|
||||
const FLAG_SEEN = '\Seen';
|
||||
const FLAG_ANSWERED = '\Answered';
|
||||
const FLAG_FLAGGED = '\Flagged';
|
||||
const FLAG_DELETED = '\Deleted';
|
||||
const FLAG_DRAFT = '\Draft';
|
||||
const FLAG_RECENT = '\Recent';
|
||||
}
|
||||
@@ -0,0 +1,366 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Storage
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Storage
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
abstract class Postman_Zend_Mail_Storage_Abstract implements Countable, ArrayAccess, SeekableIterator
|
||||
{
|
||||
/**
|
||||
* class capabilities with default values
|
||||
* @var array
|
||||
*/
|
||||
protected $_has = array('uniqueid' => true,
|
||||
'delete' => false,
|
||||
'create' => false,
|
||||
'top' => false,
|
||||
'fetchPart' => true,
|
||||
'flags' => false);
|
||||
|
||||
/**
|
||||
* current iteration position
|
||||
* @var int
|
||||
*/
|
||||
protected $_iterationPos = 0;
|
||||
|
||||
/**
|
||||
* maximum iteration position (= message count)
|
||||
* @var null|int
|
||||
*/
|
||||
protected $_iterationMax = null;
|
||||
|
||||
/**
|
||||
* used message class, change it in an extened class to extend the returned message class
|
||||
* @var string
|
||||
*/
|
||||
protected $_messageClass = 'Postman_Zend_Mail_Message';
|
||||
|
||||
/**
|
||||
* Getter for has-properties. The standard has properties
|
||||
* are: hasFolder, hasUniqueid, hasDelete, hasCreate, hasTop
|
||||
*
|
||||
* The valid values for the has-properties are:
|
||||
* - true if a feature is supported
|
||||
* - false if a feature is not supported
|
||||
* - null is it's not yet known or it can't be know if a feature is supported
|
||||
*
|
||||
* @param string $var property name
|
||||
* @return bool supported or not
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function __get($var)
|
||||
{
|
||||
if (strpos($var, 'has') === 0) {
|
||||
$var = strtolower(substr($var, 3));
|
||||
return isset($this->_has[$var]) ? $this->_has[$var] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception($var . ' not found');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a full list of features supported by the specific mail lib and the server
|
||||
*
|
||||
* @return array list of features as array(featurename => true|false[|null])
|
||||
*/
|
||||
public function getCapabilities()
|
||||
{
|
||||
return $this->_has;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Count messages messages in current box/folder
|
||||
*
|
||||
* @return int number of messages
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
abstract public function countMessages();
|
||||
|
||||
|
||||
/**
|
||||
* Get a list of messages with number and size
|
||||
*
|
||||
* @param int $id number of message
|
||||
* @return int|array size of given message of list with all messages as array(num => size)
|
||||
*/
|
||||
abstract public function getSize($id = 0);
|
||||
|
||||
|
||||
/**
|
||||
* Get a message with headers and body
|
||||
*
|
||||
* @param int $id number of message
|
||||
* @return Postman_Zend_Mail_Message
|
||||
*/
|
||||
abstract public function getMessage($id);
|
||||
|
||||
|
||||
/**
|
||||
* Get raw header of message or part
|
||||
*
|
||||
* @param int $id number of message
|
||||
* @param null|array|string $part path to part or null for messsage header
|
||||
* @param int $topLines include this many lines with header (after an empty line)
|
||||
* @return string raw header
|
||||
*/
|
||||
abstract public function getRawHeader($id, $part = null, $topLines = 0);
|
||||
|
||||
/**
|
||||
* Get raw content of message or part
|
||||
*
|
||||
* @param int $id number of message
|
||||
* @param null|array|string $part path to part or null for messsage content
|
||||
* @return string raw content
|
||||
*/
|
||||
abstract public function getRawContent($id, $part = null);
|
||||
|
||||
/**
|
||||
* Create instance with parameters
|
||||
*
|
||||
* @param array $params mail reader specific parameters
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
abstract public function __construct($params);
|
||||
|
||||
|
||||
/**
|
||||
* Destructor calls close() and therefore closes the resource.
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
$this->close();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Close resource for mail lib. If you need to control, when the resource
|
||||
* is closed. Otherwise the destructor would call this.
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
abstract public function close();
|
||||
|
||||
|
||||
/**
|
||||
* Keep the resource alive.
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
abstract public function noop();
|
||||
|
||||
/**
|
||||
* delete a message from current box/folder
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
abstract public function removeMessage($id);
|
||||
|
||||
/**
|
||||
* get unique id for one or all messages
|
||||
*
|
||||
* if storage does not support unique ids it's the same as the message number
|
||||
*
|
||||
* @param int|null $id message number
|
||||
* @return array|string message number for given message or all messages as array
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
abstract public function getUniqueId($id = null);
|
||||
|
||||
/**
|
||||
* get a message number from a unique id
|
||||
*
|
||||
* I.e. if you have a webmailer that supports deleting messages you should use unique ids
|
||||
* as parameter and use this method to translate it to message number right before calling removeMessage()
|
||||
*
|
||||
* @param string $id unique id
|
||||
* @return int message number
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
abstract public function getNumberByUniqueId($id);
|
||||
|
||||
// interface implementations follows
|
||||
|
||||
/**
|
||||
* Countable::count()
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function count()
|
||||
{
|
||||
return $this->countMessages();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ArrayAccess::offsetExists()
|
||||
*
|
||||
* @param int $id
|
||||
* @return boolean
|
||||
*/
|
||||
public function offsetExists($id)
|
||||
{
|
||||
try {
|
||||
if ($this->getMessage($id)) {
|
||||
return true;
|
||||
}
|
||||
} catch(Postman_Zend_Mail_Storage_Exception $e) {}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ArrayAccess::offsetGet()
|
||||
*
|
||||
* @param int $id
|
||||
* @return Postman_Zend_Mail_Message message object
|
||||
*/
|
||||
public function offsetGet($id)
|
||||
{
|
||||
return $this->getMessage($id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ArrayAccess::offsetSet()
|
||||
*
|
||||
* @param id $id
|
||||
* @param mixed $value
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
* @return void
|
||||
*/
|
||||
public function offsetSet($id, $value)
|
||||
{
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('cannot write mail messages via array access');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ArrayAccess::offsetUnset()
|
||||
*
|
||||
* @param int $id
|
||||
* @return boolean success
|
||||
*/
|
||||
public function offsetUnset($id)
|
||||
{
|
||||
return $this->removeMessage($id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Iterator::rewind()
|
||||
*
|
||||
* Rewind always gets the new count from the storage. Thus if you use
|
||||
* the interfaces and your scripts take long you should use reset()
|
||||
* from time to time.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function rewind()
|
||||
{
|
||||
$this->_iterationMax = $this->countMessages();
|
||||
$this->_iterationPos = 1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Iterator::current()
|
||||
*
|
||||
* @return Postman_Zend_Mail_Message current message
|
||||
*/
|
||||
public function current()
|
||||
{
|
||||
return $this->getMessage($this->_iterationPos);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Iterator::key()
|
||||
*
|
||||
* @return int id of current position
|
||||
*/
|
||||
public function key()
|
||||
{
|
||||
return $this->_iterationPos;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Iterator::next()
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function next()
|
||||
{
|
||||
++$this->_iterationPos;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Iterator::valid()
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function valid()
|
||||
{
|
||||
if ($this->_iterationMax === null) {
|
||||
$this->_iterationMax = $this->countMessages();
|
||||
}
|
||||
return $this->_iterationPos && $this->_iterationPos <= $this->_iterationMax;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* SeekableIterator::seek()
|
||||
*
|
||||
* @param int $pos
|
||||
* @return void
|
||||
* @throws OutOfBoundsException
|
||||
*/
|
||||
public function seek($pos)
|
||||
{
|
||||
if ($this->_iterationMax === null) {
|
||||
$this->_iterationMax = $this->countMessages();
|
||||
}
|
||||
|
||||
if ($pos > $this->_iterationMax) {
|
||||
throw new OutOfBoundsException('this position does not exist');
|
||||
}
|
||||
$this->_iterationPos = $pos;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Storage
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Exception.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Storage
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Postman_Zend_Mail_Storage_Exception extends Postman_Zend_Mail_Exception
|
||||
{}
|
||||
|
||||
@@ -0,0 +1,236 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Storage
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Storage
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Postman_Zend_Mail_Storage_Folder implements RecursiveIterator
|
||||
{
|
||||
/**
|
||||
* subfolders of folder array(localName => Postman_Zend_Mail_Storage_Folder folder)
|
||||
* @var array
|
||||
*/
|
||||
protected $_folders;
|
||||
|
||||
/**
|
||||
* local name (name of folder in parent folder)
|
||||
* @var string
|
||||
*/
|
||||
protected $_localName;
|
||||
|
||||
/**
|
||||
* global name (absolute name of folder)
|
||||
* @var string
|
||||
*/
|
||||
protected $_globalName;
|
||||
|
||||
/**
|
||||
* folder is selectable if folder is able to hold messages, else it's just a parent folder
|
||||
* @var bool
|
||||
*/
|
||||
protected $_selectable = true;
|
||||
|
||||
/**
|
||||
* create a new mail folder instance
|
||||
*
|
||||
* @param string $localName name of folder in current subdirectory
|
||||
* @param string $globalName absolute name of folder
|
||||
* @param bool $selectable if true folder holds messages, if false it's just a parent for subfolders
|
||||
* @param array $folders init with given instances of Postman_Zend_Mail_Storage_Folder as subfolders
|
||||
*/
|
||||
public function __construct($localName, $globalName = '', $selectable = true, array $folders = array())
|
||||
{
|
||||
$this->_localName = $localName;
|
||||
$this->_globalName = $globalName ? $globalName : $localName;
|
||||
$this->_selectable = $selectable;
|
||||
$this->_folders = $folders;
|
||||
}
|
||||
|
||||
/**
|
||||
* implements RecursiveIterator::hasChildren()
|
||||
*
|
||||
* @return bool current element has children
|
||||
*/
|
||||
public function hasChildren()
|
||||
{
|
||||
$current = $this->current();
|
||||
return $current && $current instanceof Postman_Zend_Mail_Storage_Folder && !$current->isLeaf();
|
||||
}
|
||||
|
||||
/**
|
||||
* implements RecursiveIterator::getChildren()
|
||||
*
|
||||
* @return Postman_Zend_Mail_Storage_Folder same as self::current()
|
||||
*/
|
||||
public function getChildren()
|
||||
{
|
||||
return $this->current();
|
||||
}
|
||||
|
||||
/**
|
||||
* implements Iterator::valid()
|
||||
*
|
||||
* @return bool check if there's a current element
|
||||
*/
|
||||
public function valid()
|
||||
{
|
||||
return key($this->_folders) !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* implements Iterator::next()
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function next()
|
||||
{
|
||||
next($this->_folders);
|
||||
}
|
||||
|
||||
/**
|
||||
* implements Iterator::key()
|
||||
*
|
||||
* @return string key/local name of current element
|
||||
*/
|
||||
public function key()
|
||||
{
|
||||
return key($this->_folders);
|
||||
}
|
||||
|
||||
/**
|
||||
* implements Iterator::current()
|
||||
*
|
||||
* @return Postman_Zend_Mail_Storage_Folder current folder
|
||||
*/
|
||||
public function current()
|
||||
{
|
||||
return current($this->_folders);
|
||||
}
|
||||
|
||||
/**
|
||||
* implements Iterator::rewind()
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function rewind()
|
||||
{
|
||||
reset($this->_folders);
|
||||
}
|
||||
|
||||
/**
|
||||
* get subfolder named $name
|
||||
*
|
||||
* @param string $name wanted subfolder
|
||||
* @return Postman_Zend_Mail_Storage_Folder folder named $folder
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
if (!isset($this->_folders[$name])) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception("no subfolder named $name");
|
||||
}
|
||||
|
||||
return $this->_folders[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* add or replace subfolder named $name
|
||||
*
|
||||
* @param string $name local name of subfolder
|
||||
* @param Postman_Zend_Mail_Storage_Folder $folder instance for new subfolder
|
||||
* @return null
|
||||
*/
|
||||
public function __set($name, Postman_Zend_Mail_Storage_Folder $folder)
|
||||
{
|
||||
$this->_folders[$name] = $folder;
|
||||
}
|
||||
|
||||
/**
|
||||
* remove subfolder named $name
|
||||
*
|
||||
* @param string $name local name of subfolder
|
||||
* @return null
|
||||
*/
|
||||
public function __unset($name)
|
||||
{
|
||||
unset($this->_folders[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* magic method for easy output of global name
|
||||
*
|
||||
* @return string global name of folder
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return (string)$this->getGlobalName();
|
||||
}
|
||||
|
||||
/**
|
||||
* get local name
|
||||
*
|
||||
* @return string local name
|
||||
*/
|
||||
public function getLocalName()
|
||||
{
|
||||
return $this->_localName;
|
||||
}
|
||||
|
||||
/**
|
||||
* get global name
|
||||
*
|
||||
* @return string global name
|
||||
*/
|
||||
public function getGlobalName()
|
||||
{
|
||||
return $this->_globalName;
|
||||
}
|
||||
|
||||
/**
|
||||
* is this folder selectable?
|
||||
*
|
||||
* @return bool selectable
|
||||
*/
|
||||
public function isSelectable()
|
||||
{
|
||||
return $this->_selectable;
|
||||
}
|
||||
|
||||
/**
|
||||
* check if folder has no subfolder
|
||||
*
|
||||
* @return bool true if no subfolders
|
||||
*/
|
||||
public function isLeaf()
|
||||
{
|
||||
return empty($this->_folders);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Storage
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Storage
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
interface Postman_Zend_Mail_Storage_Folder_Interface
|
||||
{
|
||||
/**
|
||||
* get root folder or given folder
|
||||
*
|
||||
* @param string $rootFolder get folder structure for given folder, else root
|
||||
* @return Postman_Zend_Mail_Storage_Folder root or wanted folder
|
||||
*/
|
||||
public function getFolders($rootFolder = null);
|
||||
|
||||
/**
|
||||
* select given folder
|
||||
*
|
||||
* folder must be selectable!
|
||||
*
|
||||
* @param Postman_Zend_Mail_Storage_Folder|string $globalName global name of folder or instance for subfolder
|
||||
* @return null
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function selectFolder($globalName);
|
||||
|
||||
|
||||
/**
|
||||
* get Postman_Zend_Mail_Storage_Folder instance for current folder
|
||||
*
|
||||
* @return Postman_Zend_Mail_Storage_Folder instance of current folder
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function getCurrentFolder();
|
||||
}
|
||||
@@ -0,0 +1,265 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Storage
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Folder
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Folder.php';
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Folder_Interface
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Folder/Interface.php';
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Maildir
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Maildir.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Storage
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Postman_Zend_Mail_Storage_Folder_Maildir extends Postman_Zend_Mail_Storage_Maildir implements Postman_Zend_Mail_Storage_Folder_Interface
|
||||
{
|
||||
/**
|
||||
* Postman_Zend_Mail_Storage_Folder root folder for folder structure
|
||||
* @var Postman_Zend_Mail_Storage_Folder
|
||||
*/
|
||||
protected $_rootFolder;
|
||||
|
||||
/**
|
||||
* rootdir of folder structure
|
||||
* @var string
|
||||
*/
|
||||
protected $_rootdir;
|
||||
|
||||
/**
|
||||
* name of current folder
|
||||
* @var string
|
||||
*/
|
||||
protected $_currentFolder;
|
||||
|
||||
/**
|
||||
* delim char for subfolders
|
||||
* @var string
|
||||
*/
|
||||
protected $_delim;
|
||||
|
||||
/**
|
||||
* Create instance with parameters
|
||||
* Supported parameters are:
|
||||
* - dirname rootdir of maildir structure
|
||||
* - delim delim char for folder structur, default is '.'
|
||||
* - folder intial selected folder, default is 'INBOX'
|
||||
*
|
||||
* @param array $params mail reader specific parameters
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function __construct($params)
|
||||
{
|
||||
if (is_array($params)) {
|
||||
$params = (object)$params;
|
||||
}
|
||||
|
||||
if (!isset($params->dirname) || !is_dir($params->dirname)) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('no valid dirname given in params');
|
||||
}
|
||||
|
||||
$this->_rootdir = rtrim($params->dirname, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
|
||||
|
||||
$this->_delim = isset($params->delim) ? $params->delim : '.';
|
||||
|
||||
$this->_buildFolderTree();
|
||||
$this->selectFolder(!empty($params->folder) ? $params->folder : 'INBOX');
|
||||
$this->_has['top'] = true;
|
||||
$this->_has['flags'] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* find all subfolders and mbox files for folder structure
|
||||
*
|
||||
* Result is save in Postman_Zend_Mail_Storage_Folder instances with the root in $this->_rootFolder.
|
||||
* $parentFolder and $parentGlobalName are only used internally for recursion.
|
||||
*
|
||||
* @return null
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
protected function _buildFolderTree()
|
||||
{
|
||||
$this->_rootFolder = new Postman_Zend_Mail_Storage_Folder('/', '/', false);
|
||||
$this->_rootFolder->INBOX = new Postman_Zend_Mail_Storage_Folder('INBOX', 'INBOX', true);
|
||||
|
||||
$dh = @opendir($this->_rootdir);
|
||||
if (!$dh) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception("can't read folders in maildir");
|
||||
}
|
||||
$dirs = array();
|
||||
while (($entry = readdir($dh)) !== false) {
|
||||
// maildir++ defines folders must start with .
|
||||
if ($entry[0] != '.' || $entry == '.' || $entry == '..') {
|
||||
continue;
|
||||
}
|
||||
if ($this->_isMaildir($this->_rootdir . $entry)) {
|
||||
$dirs[] = $entry;
|
||||
}
|
||||
}
|
||||
closedir($dh);
|
||||
|
||||
sort($dirs);
|
||||
$stack = array(null);
|
||||
$folderStack = array(null);
|
||||
$parentFolder = $this->_rootFolder;
|
||||
$parent = '.';
|
||||
|
||||
foreach ($dirs as $dir) {
|
||||
do {
|
||||
if (strpos($dir, $parent) === 0) {
|
||||
$local = substr($dir, strlen($parent));
|
||||
if (strpos($local, $this->_delim) !== false) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('error while reading maildir');
|
||||
}
|
||||
array_push($stack, $parent);
|
||||
$parent = $dir . $this->_delim;
|
||||
$folder = new Postman_Zend_Mail_Storage_Folder($local, substr($dir, 1), true);
|
||||
$parentFolder->$local = $folder;
|
||||
array_push($folderStack, $parentFolder);
|
||||
$parentFolder = $folder;
|
||||
break;
|
||||
} else if ($stack) {
|
||||
$parent = array_pop($stack);
|
||||
$parentFolder = array_pop($folderStack);
|
||||
}
|
||||
} while ($stack);
|
||||
if (!$stack) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('error while reading maildir');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get root folder or given folder
|
||||
*
|
||||
* @param string $rootFolder get folder structure for given folder, else root
|
||||
* @return Postman_Zend_Mail_Storage_Folder root or wanted folder
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function getFolders($rootFolder = null)
|
||||
{
|
||||
if (!$rootFolder || $rootFolder == 'INBOX') {
|
||||
return $this->_rootFolder;
|
||||
}
|
||||
|
||||
// rootdir is same as INBOX in maildir
|
||||
if (strpos($rootFolder, 'INBOX' . $this->_delim) === 0) {
|
||||
$rootFolder = substr($rootFolder, 6);
|
||||
}
|
||||
$currentFolder = $this->_rootFolder;
|
||||
$subname = trim($rootFolder, $this->_delim);
|
||||
while ($currentFolder) {
|
||||
@list($entry, $subname) = @explode($this->_delim, $subname, 2);
|
||||
$currentFolder = $currentFolder->$entry;
|
||||
if (!$subname) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($currentFolder->getGlobalName() != rtrim($rootFolder, $this->_delim)) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception("folder $rootFolder not found");
|
||||
}
|
||||
return $currentFolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* select given folder
|
||||
*
|
||||
* folder must be selectable!
|
||||
*
|
||||
* @param Postman_Zend_Mail_Storage_Folder|string $globalName global name of folder or instance for subfolder
|
||||
* @return null
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function selectFolder($globalName)
|
||||
{
|
||||
$this->_currentFolder = (string)$globalName;
|
||||
|
||||
// getting folder from folder tree for validation
|
||||
$folder = $this->getFolders($this->_currentFolder);
|
||||
|
||||
try {
|
||||
$this->_openMaildir($this->_rootdir . '.' . $folder->getGlobalName());
|
||||
} catch(Postman_Zend_Mail_Storage_Exception $e) {
|
||||
// check what went wrong
|
||||
if (!$folder->isSelectable()) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception("{$this->_currentFolder} is not selectable", 0, $e);
|
||||
}
|
||||
// seems like file has vanished; rebuilding folder tree - but it's still an exception
|
||||
$this->_buildFolderTree($this->_rootdir);
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('seems like the maildir has vanished, I\'ve rebuild the ' .
|
||||
'folder tree, search for an other folder and try again', 0, $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get Postman_Zend_Mail_Storage_Folder instance for current folder
|
||||
*
|
||||
* @return Postman_Zend_Mail_Storage_Folder instance of current folder
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function getCurrentFolder()
|
||||
{
|
||||
return $this->_currentFolder;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,264 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Storage
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Folder
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Folder.php';
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Folder_Interface
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Folder/Interface.php';
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Mbox
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Mbox.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Storage
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Postman_Zend_Mail_Storage_Folder_Mbox extends Postman_Zend_Mail_Storage_Mbox implements Postman_Zend_Mail_Storage_Folder_Interface
|
||||
{
|
||||
/**
|
||||
* Postman_Zend_Mail_Storage_Folder root folder for folder structure
|
||||
* @var Postman_Zend_Mail_Storage_Folder
|
||||
*/
|
||||
protected $_rootFolder;
|
||||
|
||||
/**
|
||||
* rootdir of folder structure
|
||||
* @var string
|
||||
*/
|
||||
protected $_rootdir;
|
||||
|
||||
/**
|
||||
* name of current folder
|
||||
* @var string
|
||||
*/
|
||||
protected $_currentFolder;
|
||||
|
||||
/**
|
||||
* Create instance with parameters
|
||||
*
|
||||
* Disallowed parameters are:
|
||||
* - filename use Postman_Zend_Mail_Storage_Mbox for a single file
|
||||
* Supported parameters are:
|
||||
* - dirname rootdir of mbox structure
|
||||
* - folder intial selected folder, default is 'INBOX'
|
||||
*
|
||||
* @param array $params mail reader specific parameters
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function __construct($params)
|
||||
{
|
||||
if (is_array($params)) {
|
||||
$params = (object)$params;
|
||||
}
|
||||
|
||||
if (isset($params->filename)) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('use Postman_Zend_Mail_Storage_Mbox for a single file');
|
||||
}
|
||||
|
||||
if (!isset($params->dirname) || !is_dir($params->dirname)) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('no valid dirname given in params');
|
||||
}
|
||||
|
||||
$this->_rootdir = rtrim($params->dirname, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
|
||||
|
||||
$this->_buildFolderTree($this->_rootdir);
|
||||
$this->selectFolder(!empty($params->folder) ? $params->folder : 'INBOX');
|
||||
$this->_has['top'] = true;
|
||||
$this->_has['uniqueid'] = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* find all subfolders and mbox files for folder structure
|
||||
*
|
||||
* Result is save in Postman_Zend_Mail_Storage_Folder instances with the root in $this->_rootFolder.
|
||||
* $parentFolder and $parentGlobalName are only used internally for recursion.
|
||||
*
|
||||
* @param string $currentDir call with root dir, also used for recursion.
|
||||
* @param Postman_Zend_Mail_Storage_Folder|null $parentFolder used for recursion
|
||||
* @param string $parentGlobalName used for rescursion
|
||||
* @return null
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
protected function _buildFolderTree($currentDir, $parentFolder = null, $parentGlobalName = '')
|
||||
{
|
||||
if (!$parentFolder) {
|
||||
$this->_rootFolder = new Postman_Zend_Mail_Storage_Folder('/', '/', false);
|
||||
$parentFolder = $this->_rootFolder;
|
||||
}
|
||||
|
||||
$dh = @opendir($currentDir);
|
||||
if (!$dh) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception("can't read dir $currentDir");
|
||||
}
|
||||
while (($entry = readdir($dh)) !== false) {
|
||||
// ignore hidden files for mbox
|
||||
if ($entry[0] == '.') {
|
||||
continue;
|
||||
}
|
||||
$absoluteEntry = $currentDir . $entry;
|
||||
$globalName = $parentGlobalName . DIRECTORY_SEPARATOR . $entry;
|
||||
if (is_file($absoluteEntry) && $this->_isMboxFile($absoluteEntry)) {
|
||||
$parentFolder->$entry = new Postman_Zend_Mail_Storage_Folder($entry, $globalName);
|
||||
continue;
|
||||
}
|
||||
if (!is_dir($absoluteEntry) /* || $entry == '.' || $entry == '..' */) {
|
||||
continue;
|
||||
}
|
||||
$folder = new Postman_Zend_Mail_Storage_Folder($entry, $globalName, false);
|
||||
$parentFolder->$entry = $folder;
|
||||
$this->_buildFolderTree($absoluteEntry . DIRECTORY_SEPARATOR, $folder, $globalName);
|
||||
}
|
||||
|
||||
closedir($dh);
|
||||
}
|
||||
|
||||
/**
|
||||
* get root folder or given folder
|
||||
*
|
||||
* @param string $rootFolder get folder structure for given folder, else root
|
||||
* @return Postman_Zend_Mail_Storage_Folder root or wanted folder
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function getFolders($rootFolder = null)
|
||||
{
|
||||
if (!$rootFolder) {
|
||||
return $this->_rootFolder;
|
||||
}
|
||||
|
||||
$currentFolder = $this->_rootFolder;
|
||||
$subname = trim($rootFolder, DIRECTORY_SEPARATOR);
|
||||
while ($currentFolder) {
|
||||
@list($entry, $subname) = @explode(DIRECTORY_SEPARATOR, $subname, 2);
|
||||
$currentFolder = $currentFolder->$entry;
|
||||
if (!$subname) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($currentFolder->getGlobalName() != DIRECTORY_SEPARATOR . trim($rootFolder, DIRECTORY_SEPARATOR)) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception("folder $rootFolder not found");
|
||||
}
|
||||
return $currentFolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* select given folder
|
||||
*
|
||||
* folder must be selectable!
|
||||
*
|
||||
* @param Postman_Zend_Mail_Storage_Folder|string $globalName global name of folder or instance for subfolder
|
||||
* @return null
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function selectFolder($globalName)
|
||||
{
|
||||
$this->_currentFolder = (string)$globalName;
|
||||
|
||||
// getting folder from folder tree for validation
|
||||
$folder = $this->getFolders($this->_currentFolder);
|
||||
|
||||
try {
|
||||
$this->_openMboxFile($this->_rootdir . $folder->getGlobalName());
|
||||
} catch(Postman_Zend_Mail_Storage_Exception $e) {
|
||||
// check what went wrong
|
||||
if (!$folder->isSelectable()) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception("{$this->_currentFolder} is not selectable", 0, $e);
|
||||
}
|
||||
// seems like file has vanished; rebuilding folder tree - but it's still an exception
|
||||
$this->_buildFolderTree($this->_rootdir);
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('seems like the mbox file has vanished, I\'ve rebuild the ' .
|
||||
'folder tree, search for an other folder and try again', 0, $e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get Postman_Zend_Mail_Storage_Folder instance for current folder
|
||||
*
|
||||
* @return Postman_Zend_Mail_Storage_Folder instance of current folder
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function getCurrentFolder()
|
||||
{
|
||||
return $this->_currentFolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* magic method for serialize()
|
||||
*
|
||||
* with this method you can cache the mbox class
|
||||
*
|
||||
* @return array name of variables
|
||||
*/
|
||||
public function __sleep()
|
||||
{
|
||||
return array_merge(parent::__sleep(), array('_currentFolder', '_rootFolder', '_rootdir'));
|
||||
}
|
||||
|
||||
/**
|
||||
* magic method for unserialize()
|
||||
*
|
||||
* with this method you can cache the mbox class
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function __wakeup()
|
||||
{
|
||||
// if cache is stall selectFolder() rebuilds the tree on error
|
||||
parent::__wakeup();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,644 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Storage
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Abstract
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Abstract.php';
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Imap
|
||||
*/
|
||||
require_once 'Zend/Mail/Protocol/Imap.php';
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Writable_Interface
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Writable/Interface.php';
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Folder_Interface
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Folder/Interface.php';
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Folder
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Folder.php';
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Message
|
||||
*/
|
||||
require_once 'Zend/Mail/Message.php';
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage.php';
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Storage
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Postman_Zend_Mail_Storage_Imap extends Postman_Zend_Mail_Storage_Abstract
|
||||
implements Postman_Zend_Mail_Storage_Folder_Interface, Postman_Zend_Mail_Storage_Writable_Interface
|
||||
{
|
||||
// TODO: with an internal cache we could optimize this class, or create an extra class with
|
||||
// such optimizations. Especially the various fetch calls could be combined to one cache call
|
||||
|
||||
/**
|
||||
* protocol handler
|
||||
* @var null|Postman_Zend_Mail_Protocol_Imap
|
||||
*/
|
||||
protected $_protocol;
|
||||
|
||||
/**
|
||||
* name of current folder
|
||||
* @var string
|
||||
*/
|
||||
protected $_currentFolder = '';
|
||||
|
||||
/**
|
||||
* imap flags to constants translation
|
||||
* @var array
|
||||
*/
|
||||
protected static $_knownFlags = array('\Passed' => Postman_Zend_Mail_Storage::FLAG_PASSED,
|
||||
'\Answered' => Postman_Zend_Mail_Storage::FLAG_ANSWERED,
|
||||
'\Seen' => Postman_Zend_Mail_Storage::FLAG_SEEN,
|
||||
'\Deleted' => Postman_Zend_Mail_Storage::FLAG_DELETED,
|
||||
'\Draft' => Postman_Zend_Mail_Storage::FLAG_DRAFT,
|
||||
'\Flagged' => Postman_Zend_Mail_Storage::FLAG_FLAGGED);
|
||||
|
||||
/**
|
||||
* map flags to search criterias
|
||||
* @var array
|
||||
*/
|
||||
protected static $_searchFlags = array('\Recent' => 'RECENT',
|
||||
'\Answered' => 'ANSWERED',
|
||||
'\Seen' => 'SEEN',
|
||||
'\Deleted' => 'DELETED',
|
||||
'\Draft' => 'DRAFT',
|
||||
'\Flagged' => 'FLAGGED');
|
||||
|
||||
/**
|
||||
* Count messages all messages in current box
|
||||
*
|
||||
* @return int number of messages
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function countMessages($flags = null)
|
||||
{
|
||||
if (!$this->_currentFolder) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('No selected folder to count');
|
||||
}
|
||||
|
||||
if ($flags === null) {
|
||||
return count($this->_protocol->search(array('ALL')));
|
||||
}
|
||||
|
||||
$params = array();
|
||||
foreach ((array)$flags as $flag) {
|
||||
if (isset(self::$_searchFlags[$flag])) {
|
||||
$params[] = self::$_searchFlags[$flag];
|
||||
} else {
|
||||
$params[] = 'KEYWORD';
|
||||
$params[] = $this->_protocol->escapeString($flag);
|
||||
}
|
||||
}
|
||||
return count($this->_protocol->search($params));
|
||||
}
|
||||
|
||||
/**
|
||||
* get a list of messages with number and size
|
||||
*
|
||||
* @param int $id number of message
|
||||
* @return int|array size of given message of list with all messages as array(num => size)
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function getSize($id = 0)
|
||||
{
|
||||
if ($id) {
|
||||
return $this->_protocol->fetch('RFC822.SIZE', $id);
|
||||
}
|
||||
return $this->_protocol->fetch('RFC822.SIZE', 1, INF);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a message
|
||||
*
|
||||
* @param int $id number of message
|
||||
* @return Postman_Zend_Mail_Message
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function getMessage($id)
|
||||
{
|
||||
$data = $this->_protocol->fetch(array('FLAGS', 'RFC822.HEADER'), $id);
|
||||
$header = $data['RFC822.HEADER'];
|
||||
|
||||
$flags = array();
|
||||
foreach ($data['FLAGS'] as $flag) {
|
||||
$flags[] = isset(self::$_knownFlags[$flag]) ? self::$_knownFlags[$flag] : $flag;
|
||||
}
|
||||
|
||||
return new $this->_messageClass(array('handler' => $this, 'id' => $id, 'headers' => $header, 'flags' => $flags));
|
||||
}
|
||||
|
||||
/*
|
||||
* Get raw header of message or part
|
||||
*
|
||||
* @param int $id number of message
|
||||
* @param null|array|string $part path to part or null for messsage header
|
||||
* @param int $topLines include this many lines with header (after an empty line)
|
||||
* @param int $topLines include this many lines with header (after an empty line)
|
||||
* @return string raw header
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function getRawHeader($id, $part = null, $topLines = 0)
|
||||
{
|
||||
if ($part !== null) {
|
||||
// TODO: implement
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('not implemented');
|
||||
}
|
||||
|
||||
// TODO: toplines
|
||||
return $this->_protocol->fetch('RFC822.HEADER', $id);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get raw content of message or part
|
||||
*
|
||||
* @param int $id number of message
|
||||
* @param null|array|string $part path to part or null for messsage content
|
||||
* @return string raw content
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function getRawContent($id, $part = null)
|
||||
{
|
||||
if ($part !== null) {
|
||||
// TODO: implement
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('not implemented');
|
||||
}
|
||||
|
||||
return $this->_protocol->fetch('RFC822.TEXT', $id);
|
||||
}
|
||||
|
||||
/**
|
||||
* create instance with parameters
|
||||
* Supported paramters are
|
||||
* - user username
|
||||
* - host hostname or ip address of IMAP server [optional, default = 'localhost']
|
||||
* - password password for user 'username' [optional, default = '']
|
||||
* - port port for IMAP server [optional, default = 110]
|
||||
* - ssl 'SSL' or 'TLS' for secure sockets
|
||||
* - folder select this folder [optional, default = 'INBOX']
|
||||
*
|
||||
* @param array $params mail reader specific parameters
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function __construct($params)
|
||||
{
|
||||
if (is_array($params)) {
|
||||
$params = (object)$params;
|
||||
}
|
||||
|
||||
$this->_has['flags'] = true;
|
||||
|
||||
if ($params instanceof Postman_Zend_Mail_Protocol_Imap) {
|
||||
$this->_protocol = $params;
|
||||
try {
|
||||
$this->selectFolder('INBOX');
|
||||
} catch(Postman_Zend_Mail_Storage_Exception $e) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('cannot select INBOX, is this a valid transport?', 0, $e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isset($params->user)) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('need at least user in params');
|
||||
}
|
||||
|
||||
$host = isset($params->host) ? $params->host : 'localhost';
|
||||
$password = isset($params->password) ? $params->password : '';
|
||||
$port = isset($params->port) ? $params->port : null;
|
||||
$ssl = isset($params->ssl) ? $params->ssl : false;
|
||||
|
||||
$this->_protocol = new Postman_Zend_Mail_Protocol_Imap();
|
||||
$this->_protocol->connect($host, $port, $ssl);
|
||||
if (!$this->_protocol->login($params->user, $password)) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('cannot login, user or password wrong');
|
||||
}
|
||||
$this->selectFolder(isset($params->folder) ? $params->folder : 'INBOX');
|
||||
}
|
||||
|
||||
/**
|
||||
* Close resource for mail lib. If you need to control, when the resource
|
||||
* is closed. Otherwise the destructor would call this.
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
$this->_currentFolder = '';
|
||||
$this->_protocol->logout();
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep the server busy.
|
||||
*
|
||||
* @return null
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function noop()
|
||||
{
|
||||
if (!$this->_protocol->noop()) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('could not do nothing');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a message from server. If you're doing that from a web enviroment
|
||||
* you should be careful and use a uniqueid as parameter if possible to
|
||||
* identify the message.
|
||||
*
|
||||
* @param int $id number of message
|
||||
* @return null
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function removeMessage($id)
|
||||
{
|
||||
if (!$this->_protocol->store(array(Postman_Zend_Mail_Storage::FLAG_DELETED), $id, null, '+')) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('cannot set deleted flag');
|
||||
}
|
||||
// TODO: expunge here or at close? we can handle an error here better and are more fail safe
|
||||
if (!$this->_protocol->expunge()) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('message marked as deleted, but could not expunge');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get unique id for one or all messages
|
||||
*
|
||||
* if storage does not support unique ids it's the same as the message number
|
||||
*
|
||||
* @param int|null $id message number
|
||||
* @return array|string message number for given message or all messages as array
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function getUniqueId($id = null)
|
||||
{
|
||||
if ($id) {
|
||||
return $this->_protocol->fetch('UID', $id);
|
||||
}
|
||||
|
||||
return $this->_protocol->fetch('UID', 1, INF);
|
||||
}
|
||||
|
||||
/**
|
||||
* get a message number from a unique id
|
||||
*
|
||||
* I.e. if you have a webmailer that supports deleting messages you should use unique ids
|
||||
* as parameter and use this method to translate it to message number right before calling removeMessage()
|
||||
*
|
||||
* @param string $id unique id
|
||||
* @return int message number
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function getNumberByUniqueId($id)
|
||||
{
|
||||
// TODO: use search to find number directly
|
||||
$ids = $this->getUniqueId();
|
||||
foreach ($ids as $k => $v) {
|
||||
if ($v == $id) {
|
||||
return $k;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('unique id not found');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* get root folder or given folder
|
||||
*
|
||||
* @param string $rootFolder get folder structure for given folder, else root
|
||||
* @return Postman_Zend_Mail_Storage_Folder root or wanted folder
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function getFolders($rootFolder = null)
|
||||
{
|
||||
$folders = $this->_protocol->listMailbox((string)$rootFolder);
|
||||
if (!$folders) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('folder not found');
|
||||
}
|
||||
|
||||
ksort($folders, SORT_STRING);
|
||||
$root = new Postman_Zend_Mail_Storage_Folder('/', '/', false);
|
||||
$stack = array(null);
|
||||
$folderStack = array(null);
|
||||
$parentFolder = $root;
|
||||
$parent = '';
|
||||
|
||||
foreach ($folders as $globalName => $data) {
|
||||
do {
|
||||
if (!$parent || strpos($globalName, $parent) === 0) {
|
||||
$pos = strrpos($globalName, $data['delim']);
|
||||
if ($pos === false) {
|
||||
$localName = $globalName;
|
||||
} else {
|
||||
$localName = substr($globalName, $pos + 1);
|
||||
}
|
||||
$selectable = !$data['flags'] || !in_array('\\Noselect', $data['flags']);
|
||||
|
||||
array_push($stack, $parent);
|
||||
$parent = $globalName . $data['delim'];
|
||||
$folder = new Postman_Zend_Mail_Storage_Folder($localName, $globalName, $selectable);
|
||||
$parentFolder->$localName = $folder;
|
||||
array_push($folderStack, $parentFolder);
|
||||
$parentFolder = $folder;
|
||||
break;
|
||||
} else if ($stack) {
|
||||
$parent = array_pop($stack);
|
||||
$parentFolder = array_pop($folderStack);
|
||||
}
|
||||
} while ($stack);
|
||||
if (!$stack) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('error while constructing folder tree');
|
||||
}
|
||||
}
|
||||
|
||||
return $root;
|
||||
}
|
||||
|
||||
/**
|
||||
* select given folder
|
||||
*
|
||||
* folder must be selectable!
|
||||
*
|
||||
* @param Postman_Zend_Mail_Storage_Folder|string $globalName global name of folder or instance for subfolder
|
||||
* @return null
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function selectFolder($globalName)
|
||||
{
|
||||
$this->_currentFolder = $globalName;
|
||||
if (!$this->_protocol->select($this->_currentFolder)) {
|
||||
$this->_currentFolder = '';
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('cannot change folder, maybe it does not exist');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* get Postman_Zend_Mail_Storage_Folder instance for current folder
|
||||
*
|
||||
* @return Postman_Zend_Mail_Storage_Folder instance of current folder
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function getCurrentFolder()
|
||||
{
|
||||
return $this->_currentFolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* create a new folder
|
||||
*
|
||||
* This method also creates parent folders if necessary. Some mail storages may restrict, which folder
|
||||
* may be used as parent or which chars may be used in the folder name
|
||||
*
|
||||
* @param string $name global name of folder, local name if $parentFolder is set
|
||||
* @param string|Postman_Zend_Mail_Storage_Folder $parentFolder parent folder for new folder, else root folder is parent
|
||||
* @return null
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function createFolder($name, $parentFolder = null)
|
||||
{
|
||||
// TODO: we assume / as the hierarchy delim - need to get that from the folder class!
|
||||
if ($parentFolder instanceof Postman_Zend_Mail_Storage_Folder) {
|
||||
$folder = $parentFolder->getGlobalName() . '/' . $name;
|
||||
} else if ($parentFolder != null) {
|
||||
$folder = $parentFolder . '/' . $name;
|
||||
} else {
|
||||
$folder = $name;
|
||||
}
|
||||
|
||||
if (!$this->_protocol->create($folder)) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('cannot create folder');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* remove a folder
|
||||
*
|
||||
* @param string|Postman_Zend_Mail_Storage_Folder $name name or instance of folder
|
||||
* @return null
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function removeFolder($name)
|
||||
{
|
||||
if ($name instanceof Postman_Zend_Mail_Storage_Folder) {
|
||||
$name = $name->getGlobalName();
|
||||
}
|
||||
|
||||
if (!$this->_protocol->delete($name)) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('cannot delete folder');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* rename and/or move folder
|
||||
*
|
||||
* The new name has the same restrictions as in createFolder()
|
||||
*
|
||||
* @param string|Postman_Zend_Mail_Storage_Folder $oldName name or instance of folder
|
||||
* @param string $newName new global name of folder
|
||||
* @return null
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function renameFolder($oldName, $newName)
|
||||
{
|
||||
if ($oldName instanceof Postman_Zend_Mail_Storage_Folder) {
|
||||
$oldName = $oldName->getGlobalName();
|
||||
}
|
||||
|
||||
if (!$this->_protocol->rename($oldName, $newName)) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('cannot rename folder');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* append a new message to mail storage
|
||||
*
|
||||
* @param string $message message as string or instance of message class
|
||||
* @param null|string|Postman_Zend_Mail_Storage_Folder $folder folder for new message, else current folder is taken
|
||||
* @param null|array $flags set flags for new message, else a default set is used
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
// not yet * @param string|Postman_Zend_Mail_Message|Postman_Zend_Mime_Message $message message as string or instance of message class
|
||||
public function appendMessage($message, $folder = null, $flags = null)
|
||||
{
|
||||
if ($folder === null) {
|
||||
$folder = $this->_currentFolder;
|
||||
}
|
||||
|
||||
if ($flags === null) {
|
||||
$flags = array(Postman_Zend_Mail_Storage::FLAG_SEEN);
|
||||
}
|
||||
|
||||
// TODO: handle class instances for $message
|
||||
if (!$this->_protocol->append($folder, $message, $flags)) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('cannot create message, please check if the folder exists and your flags');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* copy an existing message
|
||||
*
|
||||
* @param int $id number of message
|
||||
* @param string|Postman_Zend_Mail_Storage_Folder $folder name or instance of targer folder
|
||||
* @return null
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function copyMessage($id, $folder)
|
||||
{
|
||||
if (!$this->_protocol->copy($folder, $id)) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('cannot copy message, does the folder exist?');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* move an existing message
|
||||
*
|
||||
* NOTE: imap has no native move command, thus it's emulated with copy and delete
|
||||
*
|
||||
* @param int $id number of message
|
||||
* @param string|Postman_Zend_Mail_Storage_Folder $folder name or instance of targer folder
|
||||
* @return null
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function moveMessage($id, $folder) {
|
||||
$this->copyMessage($id, $folder);
|
||||
$this->removeMessage($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* set flags for message
|
||||
*
|
||||
* NOTE: this method can't set the recent flag.
|
||||
*
|
||||
* @param int $id number of message
|
||||
* @param array $flags new flags for message
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function setFlags($id, $flags)
|
||||
{
|
||||
if (!$this->_protocol->store($flags, $id)) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('cannot set flags, have you tried to set the recent flag or special chars?');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,475 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Storage
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Abstract
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Abstract.php';
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Message_File
|
||||
*/
|
||||
require_once 'Zend/Mail/Message/File.php';
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Storage
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Postman_Zend_Mail_Storage_Maildir extends Postman_Zend_Mail_Storage_Abstract
|
||||
{
|
||||
/**
|
||||
* used message class, change it in an extened class to extend the returned message class
|
||||
* @var string
|
||||
*/
|
||||
protected $_messageClass = 'Postman_Zend_Mail_Message_File';
|
||||
|
||||
/**
|
||||
* data of found message files in maildir dir
|
||||
* @var array
|
||||
*/
|
||||
protected $_files = array();
|
||||
|
||||
/**
|
||||
* known flag chars in filenames
|
||||
*
|
||||
* This list has to be in alphabetical order for setFlags()
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $_knownFlags = array('D' => Postman_Zend_Mail_Storage::FLAG_DRAFT,
|
||||
'F' => Postman_Zend_Mail_Storage::FLAG_FLAGGED,
|
||||
'P' => Postman_Zend_Mail_Storage::FLAG_PASSED,
|
||||
'R' => Postman_Zend_Mail_Storage::FLAG_ANSWERED,
|
||||
'S' => Postman_Zend_Mail_Storage::FLAG_SEEN,
|
||||
'T' => Postman_Zend_Mail_Storage::FLAG_DELETED);
|
||||
|
||||
// TODO: getFlags($id) for fast access if headers are not needed (i.e. just setting flags)?
|
||||
|
||||
/**
|
||||
* Count messages all messages in current box
|
||||
*
|
||||
* @return int number of messages
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function countMessages($flags = null)
|
||||
{
|
||||
if ($flags === null) {
|
||||
return count($this->_files);
|
||||
}
|
||||
|
||||
$count = 0;
|
||||
if (!is_array($flags)) {
|
||||
foreach ($this->_files as $file) {
|
||||
if (isset($file['flaglookup'][$flags])) {
|
||||
++$count;
|
||||
}
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
|
||||
$flags = array_flip($flags);
|
||||
foreach ($this->_files as $file) {
|
||||
foreach ($flags as $flag => $v) {
|
||||
if (!isset($file['flaglookup'][$flag])) {
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
++$count;
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get one or all fields from file structure. Also checks if message is valid
|
||||
*
|
||||
* @param int $id message number
|
||||
* @param string|null $field wanted field
|
||||
* @return string|array wanted field or all fields as array
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
protected function _getFileData($id, $field = null)
|
||||
{
|
||||
if (!isset($this->_files[$id - 1])) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('id does not exist');
|
||||
}
|
||||
|
||||
if (!$field) {
|
||||
return $this->_files[$id - 1];
|
||||
}
|
||||
|
||||
if (!isset($this->_files[$id - 1][$field])) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('field does not exist');
|
||||
}
|
||||
|
||||
return $this->_files[$id - 1][$field];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of messages with number and size
|
||||
*
|
||||
* @param int|null $id number of message or null for all messages
|
||||
* @return int|array size of given message of list with all messages as array(num => size)
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function getSize($id = null)
|
||||
{
|
||||
if ($id !== null) {
|
||||
$filedata = $this->_getFileData($id);
|
||||
return isset($filedata['size']) ? $filedata['size'] : filesize($filedata['filename']);
|
||||
}
|
||||
|
||||
$result = array();
|
||||
foreach ($this->_files as $num => $data) {
|
||||
$result[$num + 1] = isset($data['size']) ? $data['size'] : filesize($data['filename']);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Fetch a message
|
||||
*
|
||||
* @param int $id number of message
|
||||
* @return Postman_Zend_Mail_Message_File
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function getMessage($id)
|
||||
{
|
||||
// TODO that's ugly, would be better to let the message class decide
|
||||
if (strtolower($this->_messageClass) == 'Postman_Zend_mail_message_file' || is_subclass_of($this->_messageClass, 'Postman_Zend_mail_message_file')) {
|
||||
return new $this->_messageClass(array('file' => $this->_getFileData($id, 'filename'),
|
||||
'flags' => $this->_getFileData($id, 'flags')));
|
||||
}
|
||||
|
||||
return new $this->_messageClass(array('handler' => $this, 'id' => $id, 'headers' => $this->getRawHeader($id),
|
||||
'flags' => $this->_getFileData($id, 'flags')));
|
||||
}
|
||||
|
||||
/*
|
||||
* Get raw header of message or part
|
||||
*
|
||||
* @param int $id number of message
|
||||
* @param null|array|string $part path to part or null for messsage header
|
||||
* @param int $topLines include this many lines with header (after an empty line)
|
||||
* @return string raw header
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function getRawHeader($id, $part = null, $topLines = 0)
|
||||
{
|
||||
if ($part !== null) {
|
||||
// TODO: implement
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('not implemented');
|
||||
}
|
||||
|
||||
$fh = fopen($this->_getFileData($id, 'filename'), 'r');
|
||||
|
||||
$content = '';
|
||||
while (!feof($fh)) {
|
||||
$line = fgets($fh);
|
||||
if (!trim($line)) {
|
||||
break;
|
||||
}
|
||||
$content .= $line;
|
||||
}
|
||||
|
||||
fclose($fh);
|
||||
return $content;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get raw content of message or part
|
||||
*
|
||||
* @param int $id number of message
|
||||
* @param null|array|string $part path to part or null for messsage content
|
||||
* @return string raw content
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function getRawContent($id, $part = null)
|
||||
{
|
||||
if ($part !== null) {
|
||||
// TODO: implement
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('not implemented');
|
||||
}
|
||||
|
||||
$fh = fopen($this->_getFileData($id, 'filename'), 'r');
|
||||
|
||||
while (!feof($fh)) {
|
||||
$line = fgets($fh);
|
||||
if (!trim($line)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$content = stream_get_contents($fh);
|
||||
fclose($fh);
|
||||
return $content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create instance with parameters
|
||||
* Supported parameters are:
|
||||
* - dirname dirname of mbox file
|
||||
*
|
||||
* @param array $params mail reader specific parameters
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function __construct($params)
|
||||
{
|
||||
if (is_array($params)) {
|
||||
$params = (object)$params;
|
||||
}
|
||||
|
||||
if (!isset($params->dirname) || !is_dir($params->dirname)) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('no valid dirname given in params');
|
||||
}
|
||||
|
||||
if (!$this->_isMaildir($params->dirname)) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('invalid maildir given');
|
||||
}
|
||||
|
||||
$this->_has['top'] = true;
|
||||
$this->_has['flags'] = true;
|
||||
$this->_openMaildir($params->dirname);
|
||||
}
|
||||
|
||||
/**
|
||||
* check if a given dir is a valid maildir
|
||||
*
|
||||
* @param string $dirname name of dir
|
||||
* @return bool dir is valid maildir
|
||||
*/
|
||||
protected function _isMaildir($dirname)
|
||||
{
|
||||
if (file_exists($dirname . '/new') && !is_dir($dirname . '/new')) {
|
||||
return false;
|
||||
}
|
||||
if (file_exists($dirname . '/tmp') && !is_dir($dirname . '/tmp')) {
|
||||
return false;
|
||||
}
|
||||
return is_dir($dirname . '/cur');
|
||||
}
|
||||
|
||||
/**
|
||||
* open given dir as current maildir
|
||||
*
|
||||
* @param string $dirname name of maildir
|
||||
* @return null
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
protected function _openMaildir($dirname)
|
||||
{
|
||||
if ($this->_files) {
|
||||
$this->close();
|
||||
}
|
||||
|
||||
$dh = @opendir($dirname . '/cur/');
|
||||
if (!$dh) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('cannot open maildir');
|
||||
}
|
||||
$this->_getMaildirFiles($dh, $dirname . '/cur/');
|
||||
closedir($dh);
|
||||
|
||||
$dh = @opendir($dirname . '/new/');
|
||||
if ($dh) {
|
||||
$this->_getMaildirFiles($dh, $dirname . '/new/', array(Postman_Zend_Mail_Storage::FLAG_RECENT));
|
||||
closedir($dh);
|
||||
} else if (file_exists($dirname . '/new/')) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('cannot read recent mails in maildir');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* find all files in opened dir handle and add to maildir files
|
||||
*
|
||||
* @param resource $dh dir handle used for search
|
||||
* @param string $dirname dirname of dir in $dh
|
||||
* @param array $default_flags default flags for given dir
|
||||
* @return null
|
||||
*/
|
||||
protected function _getMaildirFiles($dh, $dirname, $default_flags = array())
|
||||
{
|
||||
while (($entry = readdir($dh)) !== false) {
|
||||
if ($entry[0] == '.' || !is_file($dirname . $entry)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@list($uniq, $info) = explode(':', $entry, 2);
|
||||
@list(,$size) = explode(',', $uniq, 2);
|
||||
if ($size && $size[0] == 'S' && $size[1] == '=') {
|
||||
$size = substr($size, 2);
|
||||
}
|
||||
if (!ctype_digit($size)) {
|
||||
$size = null;
|
||||
}
|
||||
@list($version, $flags) = explode(',', $info, 2);
|
||||
if ($version != 2) {
|
||||
$flags = '';
|
||||
}
|
||||
|
||||
$named_flags = $default_flags;
|
||||
$length = strlen($flags);
|
||||
for ($i = 0; $i < $length; ++$i) {
|
||||
$flag = $flags[$i];
|
||||
$named_flags[$flag] = isset(self::$_knownFlags[$flag]) ? self::$_knownFlags[$flag] : $flag;
|
||||
}
|
||||
|
||||
$data = array('uniq' => $uniq,
|
||||
'flags' => $named_flags,
|
||||
'flaglookup' => array_flip($named_flags),
|
||||
'filename' => $dirname . $entry);
|
||||
if ($size !== null) {
|
||||
$data['size'] = (int)$size;
|
||||
}
|
||||
$this->_files[] = $data;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Close resource for mail lib. If you need to control, when the resource
|
||||
* is closed. Otherwise the destructor would call this.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
$this->_files = array();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Waste some CPU cycles doing nothing.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function noop()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* stub for not supported message deletion
|
||||
*
|
||||
* @return null
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function removeMessage($id)
|
||||
{
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('maildir is (currently) read-only');
|
||||
}
|
||||
|
||||
/**
|
||||
* get unique id for one or all messages
|
||||
*
|
||||
* if storage does not support unique ids it's the same as the message number
|
||||
*
|
||||
* @param int|null $id message number
|
||||
* @return array|string message number for given message or all messages as array
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function getUniqueId($id = null)
|
||||
{
|
||||
if ($id) {
|
||||
return $this->_getFileData($id, 'uniq');
|
||||
}
|
||||
|
||||
$ids = array();
|
||||
foreach ($this->_files as $num => $file) {
|
||||
$ids[$num + 1] = $file['uniq'];
|
||||
}
|
||||
return $ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* get a message number from a unique id
|
||||
*
|
||||
* I.e. if you have a webmailer that supports deleting messages you should use unique ids
|
||||
* as parameter and use this method to translate it to message number right before calling removeMessage()
|
||||
*
|
||||
* @param string $id unique id
|
||||
* @return int message number
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function getNumberByUniqueId($id)
|
||||
{
|
||||
foreach ($this->_files as $num => $file) {
|
||||
if ($file['uniq'] == $id) {
|
||||
return $num + 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('unique id not found');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,447 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Storage
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Loader
|
||||
* May be used in constructor, but commented out for now
|
||||
*/
|
||||
// require_once 'Zend/Loader.php';
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Abstract
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Abstract.php';
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Message_File
|
||||
*/
|
||||
require_once 'Zend/Mail/Message/File.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Storage
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Postman_Zend_Mail_Storage_Mbox extends Postman_Zend_Mail_Storage_Abstract
|
||||
{
|
||||
/**
|
||||
* file handle to mbox file
|
||||
* @var null|resource
|
||||
*/
|
||||
protected $_fh;
|
||||
|
||||
/**
|
||||
* filename of mbox file for __wakeup
|
||||
* @var string
|
||||
*/
|
||||
protected $_filename;
|
||||
|
||||
/**
|
||||
* modification date of mbox file for __wakeup
|
||||
* @var int
|
||||
*/
|
||||
protected $_filemtime;
|
||||
|
||||
/**
|
||||
* start and end position of messages as array('start' => start, 'seperator' => headersep, 'end' => end)
|
||||
* @var array
|
||||
*/
|
||||
protected $_positions;
|
||||
|
||||
/**
|
||||
* used message class, change it in an extened class to extend the returned message class
|
||||
* @var string
|
||||
*/
|
||||
protected $_messageClass = 'Postman_Zend_Mail_Message_File';
|
||||
|
||||
/**
|
||||
* Count messages all messages in current box
|
||||
*
|
||||
* @return int number of messages
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function countMessages()
|
||||
{
|
||||
return count($this->_positions);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a list of messages with number and size
|
||||
*
|
||||
* @param int|null $id number of message or null for all messages
|
||||
* @return int|array size of given message of list with all messages as array(num => size)
|
||||
*/
|
||||
public function getSize($id = 0)
|
||||
{
|
||||
if ($id) {
|
||||
$pos = $this->_positions[$id - 1];
|
||||
return $pos['end'] - $pos['start'];
|
||||
}
|
||||
|
||||
$result = array();
|
||||
foreach ($this->_positions as $num => $pos) {
|
||||
$result[$num + 1] = $pos['end'] - $pos['start'];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get positions for mail message or throw exeption if id is invalid
|
||||
*
|
||||
* @param int $id number of message
|
||||
* @return array positions as in _positions
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
protected function _getPos($id)
|
||||
{
|
||||
if (!isset($this->_positions[$id - 1])) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('id does not exist');
|
||||
}
|
||||
|
||||
return $this->_positions[$id - 1];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetch a message
|
||||
*
|
||||
* @param int $id number of message
|
||||
* @return Postman_Zend_Mail_Message_File
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function getMessage($id)
|
||||
{
|
||||
// TODO that's ugly, would be better to let the message class decide
|
||||
if (strtolower($this->_messageClass) == 'Postman_Zend_mail_message_file' || is_subclass_of($this->_messageClass, 'Postman_Zend_mail_message_file')) {
|
||||
// TODO top/body lines
|
||||
$messagePos = $this->_getPos($id);
|
||||
return new $this->_messageClass(array('file' => $this->_fh, 'startPos' => $messagePos['start'],
|
||||
'endPos' => $messagePos['end']));
|
||||
}
|
||||
|
||||
$bodyLines = 0; // TODO: need a way to change that
|
||||
|
||||
$message = $this->getRawHeader($id);
|
||||
// file pointer is after headers now
|
||||
if ($bodyLines) {
|
||||
$message .= "\n";
|
||||
while ($bodyLines-- && ftell($this->_fh) < $this->_positions[$id - 1]['end']) {
|
||||
$message .= fgets($this->_fh);
|
||||
}
|
||||
}
|
||||
|
||||
return new $this->_messageClass(array('handler' => $this, 'id' => $id, 'headers' => $message));
|
||||
}
|
||||
|
||||
/*
|
||||
* Get raw header of message or part
|
||||
*
|
||||
* @param int $id number of message
|
||||
* @param null|array|string $part path to part or null for messsage header
|
||||
* @param int $topLines include this many lines with header (after an empty line)
|
||||
* @return string raw header
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function getRawHeader($id, $part = null, $topLines = 0)
|
||||
{
|
||||
if ($part !== null) {
|
||||
// TODO: implement
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('not implemented');
|
||||
}
|
||||
$messagePos = $this->_getPos($id);
|
||||
// TODO: toplines
|
||||
return stream_get_contents($this->_fh, $messagePos['separator'] - $messagePos['start'], $messagePos['start']);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get raw content of message or part
|
||||
*
|
||||
* @param int $id number of message
|
||||
* @param null|array|string $part path to part or null for messsage content
|
||||
* @return string raw content
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function getRawContent($id, $part = null)
|
||||
{
|
||||
if ($part !== null) {
|
||||
// TODO: implement
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('not implemented');
|
||||
}
|
||||
$messagePos = $this->_getPos($id);
|
||||
return stream_get_contents($this->_fh, $messagePos['end'] - $messagePos['separator'], $messagePos['separator']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create instance with parameters
|
||||
* Supported parameters are:
|
||||
* - filename filename of mbox file
|
||||
*
|
||||
* @param array $params mail reader specific parameters
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function __construct($params)
|
||||
{
|
||||
if (is_array($params)) {
|
||||
$params = (object)$params;
|
||||
}
|
||||
|
||||
if (!isset($params->filename) /* || Postman_Zend_Loader::isReadable($params['filename']) */) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('no valid filename given in params');
|
||||
}
|
||||
|
||||
$this->_openMboxFile($params->filename);
|
||||
$this->_has['top'] = true;
|
||||
$this->_has['uniqueid'] = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* check if given file is a mbox file
|
||||
*
|
||||
* if $file is a resource its file pointer is moved after the first line
|
||||
*
|
||||
* @param resource|string $file stream resource of name of file
|
||||
* @param bool $fileIsString file is string or resource
|
||||
* @return bool file is mbox file
|
||||
*/
|
||||
protected function _isMboxFile($file, $fileIsString = true)
|
||||
{
|
||||
if ($fileIsString) {
|
||||
$file = @fopen($file, 'r');
|
||||
if (!$file) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
fseek($file, 0);
|
||||
}
|
||||
|
||||
$result = false;
|
||||
|
||||
$line = fgets($file);
|
||||
if (strpos($line, 'From ') === 0) {
|
||||
$result = true;
|
||||
}
|
||||
|
||||
if ($fileIsString) {
|
||||
@fclose($file);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* open given file as current mbox file
|
||||
*
|
||||
* @param string $filename filename of mbox file
|
||||
* @return null
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
protected function _openMboxFile($filename)
|
||||
{
|
||||
if ($this->_fh) {
|
||||
$this->close();
|
||||
}
|
||||
|
||||
$this->_fh = @fopen($filename, 'r');
|
||||
if (!$this->_fh) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('cannot open mbox file');
|
||||
}
|
||||
$this->_filename = $filename;
|
||||
$this->_filemtime = filemtime($this->_filename);
|
||||
|
||||
if (!$this->_isMboxFile($this->_fh, false)) {
|
||||
@fclose($this->_fh);
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('file is not a valid mbox format');
|
||||
}
|
||||
|
||||
$messagePos = array('start' => ftell($this->_fh), 'separator' => 0, 'end' => 0);
|
||||
while (($line = fgets($this->_fh)) !== false) {
|
||||
if (strpos($line, 'From ') === 0) {
|
||||
$messagePos['end'] = ftell($this->_fh) - strlen($line) - 2; // + newline
|
||||
if (!$messagePos['separator']) {
|
||||
$messagePos['separator'] = $messagePos['end'];
|
||||
}
|
||||
$this->_positions[] = $messagePos;
|
||||
$messagePos = array('start' => ftell($this->_fh), 'separator' => 0, 'end' => 0);
|
||||
}
|
||||
if (!$messagePos['separator'] && !trim($line)) {
|
||||
$messagePos['separator'] = ftell($this->_fh);
|
||||
}
|
||||
}
|
||||
|
||||
$messagePos['end'] = ftell($this->_fh);
|
||||
if (!$messagePos['separator']) {
|
||||
$messagePos['separator'] = $messagePos['end'];
|
||||
}
|
||||
$this->_positions[] = $messagePos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close resource for mail lib. If you need to control, when the resource
|
||||
* is closed. Otherwise the destructor would call this.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
@fclose($this->_fh);
|
||||
$this->_positions = array();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Waste some CPU cycles doing nothing.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function noop()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* stub for not supported message deletion
|
||||
*
|
||||
* @return null
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function removeMessage($id)
|
||||
{
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('mbox is read-only');
|
||||
}
|
||||
|
||||
/**
|
||||
* get unique id for one or all messages
|
||||
*
|
||||
* Mbox does not support unique ids (yet) - it's always the same as the message number.
|
||||
* That shouldn't be a problem, because we can't change mbox files. Therefor the message
|
||||
* number is save enough.
|
||||
*
|
||||
* @param int|null $id message number
|
||||
* @return array|string message number for given message or all messages as array
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function getUniqueId($id = null)
|
||||
{
|
||||
if ($id) {
|
||||
// check if id exists
|
||||
$this->_getPos($id);
|
||||
return $id;
|
||||
}
|
||||
|
||||
$range = range(1, $this->countMessages());
|
||||
return array_combine($range, $range);
|
||||
}
|
||||
|
||||
/**
|
||||
* get a message number from a unique id
|
||||
*
|
||||
* I.e. if you have a webmailer that supports deleting messages you should use unique ids
|
||||
* as parameter and use this method to translate it to message number right before calling removeMessage()
|
||||
*
|
||||
* @param string $id unique id
|
||||
* @return int message number
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function getNumberByUniqueId($id)
|
||||
{
|
||||
// check if id exists
|
||||
$this->_getPos($id);
|
||||
return $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* magic method for serialize()
|
||||
*
|
||||
* with this method you can cache the mbox class
|
||||
*
|
||||
* @return array name of variables
|
||||
*/
|
||||
public function __sleep()
|
||||
{
|
||||
return array('_filename', '_positions', '_filemtime');
|
||||
}
|
||||
|
||||
/**
|
||||
* magic method for unserialize()
|
||||
*
|
||||
* with this method you can cache the mbox class
|
||||
* for cache validation the mtime of the mbox file is used
|
||||
*
|
||||
* @return null
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function __wakeup()
|
||||
{
|
||||
if ($this->_filemtime != @filemtime($this->_filename)) {
|
||||
$this->close();
|
||||
$this->_openMboxFile($this->_filename);
|
||||
} else {
|
||||
$this->_fh = @fopen($this->_filename, 'r');
|
||||
if (!$this->_fh) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('cannot open mbox file');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,328 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Storage
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Abstract
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Abstract.php';
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Pop3
|
||||
*/
|
||||
require_once 'Zend/Mail/Protocol/Pop3.php';
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Message
|
||||
*/
|
||||
require_once 'Zend/Mail/Message.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Storage
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Postman_Zend_Mail_Storage_Pop3 extends Postman_Zend_Mail_Storage_Abstract
|
||||
{
|
||||
/**
|
||||
* protocol handler
|
||||
* @var null|Postman_Zend_Mail_Protocol_Pop3
|
||||
*/
|
||||
protected $_protocol;
|
||||
|
||||
|
||||
/**
|
||||
* Count messages all messages in current box
|
||||
*
|
||||
* @return int number of messages
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function countMessages()
|
||||
{
|
||||
$this->_protocol->status($count, $null);
|
||||
return (int)$count;
|
||||
}
|
||||
|
||||
/**
|
||||
* get a list of messages with number and size
|
||||
*
|
||||
* @param int $id number of message
|
||||
* @return int|array size of given message of list with all messages as array(num => size)
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function getSize($id = 0)
|
||||
{
|
||||
$id = $id ? $id : null;
|
||||
return $this->_protocol->getList($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a message
|
||||
*
|
||||
* @param int $id number of message
|
||||
* @return Postman_Zend_Mail_Message
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function getMessage($id)
|
||||
{
|
||||
$bodyLines = 0;
|
||||
$message = $this->_protocol->top($id, $bodyLines, true);
|
||||
|
||||
return new $this->_messageClass(array('handler' => $this, 'id' => $id, 'headers' => $message,
|
||||
'noToplines' => $bodyLines < 1));
|
||||
}
|
||||
|
||||
/*
|
||||
* Get raw header of message or part
|
||||
*
|
||||
* @param int $id number of message
|
||||
* @param null|array|string $part path to part or null for messsage header
|
||||
* @param int $topLines include this many lines with header (after an empty line)
|
||||
* @return string raw header
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function getRawHeader($id, $part = null, $topLines = 0)
|
||||
{
|
||||
if ($part !== null) {
|
||||
// TODO: implement
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('not implemented');
|
||||
}
|
||||
|
||||
return $this->_protocol->top($id, 0, true);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get raw content of message or part
|
||||
*
|
||||
* @param int $id number of message
|
||||
* @param null|array|string $part path to part or null for messsage content
|
||||
* @return string raw content
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function getRawContent($id, $part = null)
|
||||
{
|
||||
if ($part !== null) {
|
||||
// TODO: implement
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('not implemented');
|
||||
}
|
||||
|
||||
$content = $this->_protocol->retrieve($id);
|
||||
// TODO: find a way to avoid decoding the headers
|
||||
Postman_Zend_Mime_Decode::splitMessage($content, $null, $body);
|
||||
return $body;
|
||||
}
|
||||
|
||||
/**
|
||||
* create instance with parameters
|
||||
* Supported paramters are
|
||||
* - host hostname or ip address of POP3 server
|
||||
* - user username
|
||||
* - password password for user 'username' [optional, default = '']
|
||||
* - port port for POP3 server [optional, default = 110]
|
||||
* - ssl 'SSL' or 'TLS' for secure sockets
|
||||
*
|
||||
* @param array $params mail reader specific parameters
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function __construct($params)
|
||||
{
|
||||
if (is_array($params)) {
|
||||
$params = (object)$params;
|
||||
}
|
||||
|
||||
$this->_has['fetchPart'] = false;
|
||||
$this->_has['top'] = null;
|
||||
$this->_has['uniqueid'] = null;
|
||||
|
||||
if ($params instanceof Postman_Zend_Mail_Protocol_Pop3) {
|
||||
$this->_protocol = $params;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isset($params->user)) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('need at least user in params');
|
||||
}
|
||||
|
||||
$host = isset($params->host) ? $params->host : 'localhost';
|
||||
$password = isset($params->password) ? $params->password : '';
|
||||
$port = isset($params->port) ? $params->port : null;
|
||||
$ssl = isset($params->ssl) ? $params->ssl : false;
|
||||
|
||||
$this->_protocol = new Postman_Zend_Mail_Protocol_Pop3();
|
||||
$this->_protocol->connect($host, $port, $ssl);
|
||||
$this->_protocol->login($params->user, $password);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close resource for mail lib. If you need to control, when the resource
|
||||
* is closed. Otherwise the destructor would call this.
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function close()
|
||||
{
|
||||
$this->_protocol->logout();
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep the server busy.
|
||||
*
|
||||
* @return null
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function noop()
|
||||
{
|
||||
return $this->_protocol->noop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a message from server. If you're doing that from a web enviroment
|
||||
* you should be careful and use a uniqueid as parameter if possible to
|
||||
* identify the message.
|
||||
*
|
||||
* @param int $id number of message
|
||||
* @return null
|
||||
* @throws Postman_Zend_Mail_Protocol_Exception
|
||||
*/
|
||||
public function removeMessage($id)
|
||||
{
|
||||
$this->_protocol->delete($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* get unique id for one or all messages
|
||||
*
|
||||
* if storage does not support unique ids it's the same as the message number
|
||||
*
|
||||
* @param int|null $id message number
|
||||
* @return array|string message number for given message or all messages as array
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function getUniqueId($id = null)
|
||||
{
|
||||
if (!$this->hasUniqueid) {
|
||||
if ($id) {
|
||||
return $id;
|
||||
}
|
||||
$count = $this->countMessages();
|
||||
if ($count < 1) {
|
||||
return array();
|
||||
}
|
||||
$range = range(1, $count);
|
||||
return array_combine($range, $range);
|
||||
}
|
||||
|
||||
return $this->_protocol->uniqueid($id);
|
||||
}
|
||||
|
||||
/**
|
||||
* get a message number from a unique id
|
||||
*
|
||||
* I.e. if you have a webmailer that supports deleting messages you should use unique ids
|
||||
* as parameter and use this method to translate it to message number right before calling removeMessage()
|
||||
*
|
||||
* @param string $id unique id
|
||||
* @return int message number
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function getNumberByUniqueId($id)
|
||||
{
|
||||
if (!$this->hasUniqueid) {
|
||||
return $id;
|
||||
}
|
||||
|
||||
$ids = $this->getUniqueId();
|
||||
foreach ($ids as $k => $v) {
|
||||
if ($v == $id) {
|
||||
return $k;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
require_once 'Zend/Mail/Storage/Exception.php';
|
||||
throw new Postman_Zend_Mail_Storage_Exception('unique id not found');
|
||||
}
|
||||
|
||||
/**
|
||||
* Special handling for hasTop and hasUniqueid. The headers of the first message is
|
||||
* retrieved if Top wasn't needed/tried yet.
|
||||
*
|
||||
* @see Postman_Zend_Mail_Storage_Abstract:__get()
|
||||
* @param string $var
|
||||
* @return string
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function __get($var)
|
||||
{
|
||||
$result = parent::__get($var);
|
||||
if ($result !== null) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
if (strtolower($var) == 'hastop') {
|
||||
if ($this->_protocol->hasTop === null) {
|
||||
// need to make a real call, because not all server are honest in their capas
|
||||
try {
|
||||
$this->_protocol->top(1, 0, false);
|
||||
} catch(Postman_Zend_Mail_Exception $e) {
|
||||
// ignoring error
|
||||
}
|
||||
}
|
||||
$this->_has['top'] = $this->_protocol->hasTop;
|
||||
return $this->_protocol->hasTop;
|
||||
}
|
||||
|
||||
if (strtolower($var) == 'hasuniqueid') {
|
||||
$id = null;
|
||||
try {
|
||||
$id = $this->_protocol->uniqueid(1);
|
||||
} catch(Postman_Zend_Mail_Exception $e) {
|
||||
// ignoring error
|
||||
}
|
||||
$this->_has['uniqueid'] = $id ? true : false;
|
||||
return $this->_has['uniqueid'];
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Storage
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Storage
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
|
||||
interface Postman_Zend_Mail_Storage_Writable_Interface
|
||||
{
|
||||
/**
|
||||
* create a new folder
|
||||
*
|
||||
* This method also creates parent folders if necessary. Some mail storages may restrict, which folder
|
||||
* may be used as parent or which chars may be used in the folder name
|
||||
*
|
||||
* @param string $name global name of folder, local name if $parentFolder is set
|
||||
* @param string|Postman_Zend_Mail_Storage_Folder $parentFolder parent folder for new folder, else root folder is parent
|
||||
* @return null
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function createFolder($name, $parentFolder = null);
|
||||
|
||||
/**
|
||||
* remove a folder
|
||||
*
|
||||
* @param string|Postman_Zend_Mail_Storage_Folder $name name or instance of folder
|
||||
* @return null
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function removeFolder($name);
|
||||
|
||||
/**
|
||||
* rename and/or move folder
|
||||
*
|
||||
* The new name has the same restrictions as in createFolder()
|
||||
*
|
||||
* @param string|Postman_Zend_Mail_Storage_Folder $oldName name or instance of folder
|
||||
* @param string $newName new global name of folder
|
||||
* @return null
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function renameFolder($oldName, $newName);
|
||||
|
||||
/**
|
||||
* append a new message to mail storage
|
||||
*
|
||||
* @param string|Postman_Zend_Mail_Message|Postman_Zend_Mime_Message $message message as string or instance of message class
|
||||
* @param null|string|Postman_Zend_Mail_Storage_Folder $folder folder for new message, else current folder is taken
|
||||
* @param null|array $flags set flags for new message, else a default set is used
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function appendMessage($message, $folder = null, $flags = null);
|
||||
|
||||
/**
|
||||
* copy an existing message
|
||||
*
|
||||
* @param int $id number of message
|
||||
* @param string|Postman_Zend_Mail_Storage_Folder $folder name or instance of targer folder
|
||||
* @return null
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function copyMessage($id, $folder);
|
||||
|
||||
/**
|
||||
* move an existing message
|
||||
*
|
||||
* @param int $id number of message
|
||||
* @param string|Postman_Zend_Mail_Storage_Folder $folder name or instance of targer folder
|
||||
* @return null
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function moveMessage($id, $folder);
|
||||
|
||||
/**
|
||||
* set flags for message
|
||||
*
|
||||
* NOTE: this method can't set the recent flag.
|
||||
*
|
||||
* @param int $id number of message
|
||||
* @param array $flags new flags for message
|
||||
* @throws Postman_Zend_Mail_Storage_Exception
|
||||
*/
|
||||
public function setFlags($id, $flags);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,366 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Transport
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mime
|
||||
*/
|
||||
// require_once 'Zend/Mime.php';
|
||||
|
||||
|
||||
/**
|
||||
* Abstract for sending eMails through different
|
||||
* ways of transport
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Transport
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
abstract class Postman_Zend_Mail_Transport_Abstract
|
||||
{
|
||||
/**
|
||||
* Mail body
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
public $body = '';
|
||||
|
||||
/**
|
||||
* MIME boundary
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
public $boundary = '';
|
||||
|
||||
/**
|
||||
* Mail header string
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
public $header = '';
|
||||
|
||||
/**
|
||||
* Array of message headers
|
||||
* @var array
|
||||
* @access protected
|
||||
*/
|
||||
protected $_headers = array();
|
||||
|
||||
/**
|
||||
* Message is a multipart message
|
||||
* @var boolean
|
||||
* @access protected
|
||||
*/
|
||||
protected $_isMultipart = false;
|
||||
|
||||
/**
|
||||
* Postman_Zend_Mail object
|
||||
* @var false|Postman_Zend_Mail
|
||||
* @access protected
|
||||
*/
|
||||
protected $_mail = false;
|
||||
|
||||
/**
|
||||
* Array of message parts
|
||||
* @var array
|
||||
* @access protected
|
||||
*/
|
||||
protected $_parts = array();
|
||||
|
||||
/**
|
||||
* Recipients string
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
public $recipients = '';
|
||||
|
||||
/**
|
||||
* EOL character string used by transport
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
public $EOL = "\r\n";
|
||||
|
||||
/**
|
||||
* Send an email independent from the used transport
|
||||
*
|
||||
* The requisite information for the email will be found in the following
|
||||
* properties:
|
||||
*
|
||||
* - {@link $recipients} - list of recipients (string)
|
||||
* - {@link $header} - message header
|
||||
* - {@link $body} - message body
|
||||
*/
|
||||
abstract protected function _sendMail();
|
||||
|
||||
/**
|
||||
* Return all mail headers as an array
|
||||
*
|
||||
* If a boundary is given, a multipart header is generated with a
|
||||
* Content-Type of either multipart/alternative or multipart/mixed depending
|
||||
* on the mail parts present in the {@link $_mail Postman_Zend_Mail object} present.
|
||||
*
|
||||
* @param string $boundary
|
||||
* @return array
|
||||
*/
|
||||
protected function _getHeaders($boundary)
|
||||
{
|
||||
if (null !== $boundary) {
|
||||
// Build multipart mail
|
||||
$type = $this->_mail->getType();
|
||||
if (!$type) {
|
||||
if ($this->_mail->hasAttachments) {
|
||||
$type = Postman_Zend_Mime::MULTIPART_MIXED;
|
||||
} elseif ($this->_mail->getBodyText() && $this->_mail->getBodyHtml() ) {
|
||||
$type = Postman_Zend_Mime::MULTIPART_ALTERNATIVE;
|
||||
} else {
|
||||
$type = Postman_Zend_Mime::MULTIPART_MIXED;
|
||||
}
|
||||
}
|
||||
|
||||
$this->_headers['Content-Type'] = array(
|
||||
$type . ';'
|
||||
. $this->EOL
|
||||
. " " . 'boundary="' . $boundary . '"'
|
||||
);
|
||||
$this->boundary = $boundary;
|
||||
}
|
||||
|
||||
$this->_headers['MIME-Version'] = array('1.0');
|
||||
|
||||
return $this->_headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepend header name to header value
|
||||
*
|
||||
* @param string $item
|
||||
* @param string $key
|
||||
* @param string $prefix
|
||||
* @static
|
||||
* @access protected
|
||||
* @return void
|
||||
*/
|
||||
protected static function _formatHeader(&$item, $key, $prefix)
|
||||
{
|
||||
$item = $prefix . ': ' . $item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare header string for use in transport
|
||||
*
|
||||
* Prepares and generates {@link $header} based on the headers provided.
|
||||
*
|
||||
* @param mixed $headers
|
||||
* @access protected
|
||||
* @return void
|
||||
* @throws Postman_Zend_Mail_Transport_Exception if any header lines exceed 998
|
||||
* characters
|
||||
*/
|
||||
protected function _prepareHeaders($headers)
|
||||
{
|
||||
if (!$this->_mail) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Transport_Exception
|
||||
*/
|
||||
require_once 'Exception.php';
|
||||
throw new Postman_Zend_Mail_Transport_Exception('Missing Postman_Zend_Mail object in _mail property');
|
||||
}
|
||||
|
||||
if( PostmanOptions::getInstance()->is_php_compatibility_enabled() ) {
|
||||
|
||||
add_filter( 'post_smtp_incompatible_php', '__return_true' );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter to manage \r\n compalibility issues with some PHP versions
|
||||
*
|
||||
* @since 2.4.5
|
||||
* @version 1.0.0
|
||||
*/
|
||||
$incompatible_php = apply_filters( 'post_smtp_incompatible_php', false );
|
||||
|
||||
$this->header = '';
|
||||
|
||||
foreach ($headers as $header => $content) {
|
||||
if (isset($content['append'])) {
|
||||
unset($content['append']);
|
||||
$value = implode(',' . $this->EOL . ' ', $content);
|
||||
$this->header .= $incompatible_php ? $header . ': ' . $value . "\r\n" : $header . ': ' . $value . $this->EOL;
|
||||
} else {
|
||||
|
||||
array_walk($content, array(get_class($this), '_formatHeader'), $header);
|
||||
$this->header .= $incompatible_php ? implode($this->EOL, $content) . "\r\n" : implode($this->EOL, $content) . $this->EOL;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Sanity check on headers -- should not be > 998 characters
|
||||
$sane = true;
|
||||
foreach (explode($this->EOL, $this->header) as $line) {
|
||||
if (strlen(trim($line)) > 998) {
|
||||
$sane = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$sane) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Transport_Exception
|
||||
*/
|
||||
require_once 'Exception.php';
|
||||
throw new Postman_Zend_Mail_Exception('At least one mail header line is too long');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate MIME compliant message from the current configuration
|
||||
*
|
||||
* If both a text and HTML body are present, generates a
|
||||
* multipart/alternative Postman_Zend_Mime_Part containing the headers and contents
|
||||
* of each. Otherwise, uses whichever of the text or HTML parts present.
|
||||
*
|
||||
* The content part is then prepended to the list of Postman_Zend_Mime_Parts for
|
||||
* this message.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function _buildBody()
|
||||
{
|
||||
if (($text = $this->_mail->getBodyText())
|
||||
&& ($html = $this->_mail->getBodyHtml()))
|
||||
{
|
||||
// Generate unique boundary for multipart/alternative
|
||||
$mime = new Postman_Zend_Mime(null);
|
||||
$boundaryLine = $mime->boundaryLine($this->EOL);
|
||||
$boundaryEnd = $mime->mimeEnd($this->EOL);
|
||||
|
||||
$text->disposition = false;
|
||||
$html->disposition = false;
|
||||
|
||||
$body = $boundaryLine
|
||||
. $text->getHeaders($this->EOL)
|
||||
. $this->EOL
|
||||
. $text->getContent($this->EOL)
|
||||
. $this->EOL
|
||||
. $boundaryLine
|
||||
. $html->getHeaders($this->EOL)
|
||||
. $this->EOL
|
||||
. $html->getContent($this->EOL)
|
||||
. $this->EOL
|
||||
. $boundaryEnd;
|
||||
|
||||
$mp = new Postman_Zend_Mime_Part($body);
|
||||
$mp->type = Postman_Zend_Mime::MULTIPART_ALTERNATIVE;
|
||||
$mp->boundary = $mime->boundary();
|
||||
|
||||
$this->_isMultipart = true;
|
||||
|
||||
// Ensure first part contains text alternatives
|
||||
array_unshift($this->_parts, $mp);
|
||||
|
||||
// Get headers
|
||||
$this->_headers = $this->_mail->getHeaders();
|
||||
return;
|
||||
}
|
||||
|
||||
// If not multipart, then get the body
|
||||
if (false !== ($body = $this->_mail->getBodyHtml())) {
|
||||
array_unshift($this->_parts, $body);
|
||||
} elseif (false !== ($body = $this->_mail->getBodyText())) {
|
||||
array_unshift($this->_parts, $body);
|
||||
}
|
||||
|
||||
if (!$body) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Transport_Exception
|
||||
*/
|
||||
require_once 'Exception.php';
|
||||
throw new Postman_Zend_Mail_Transport_Exception('This email has empty body');
|
||||
}
|
||||
|
||||
// Get headers
|
||||
$this->_headers = $this->_mail->getHeaders();
|
||||
$headers = $body->getHeadersArray($this->EOL);
|
||||
foreach ($headers as $header) {
|
||||
// Headers in Postman_Zend_Mime_Part are kept as arrays with two elements, a
|
||||
// key and a value
|
||||
$this->_headers[$header[0]] = array($header[1]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a mail using this transport
|
||||
*
|
||||
* @param Postman_Zend_Mail $mail
|
||||
* @access public
|
||||
* @return void
|
||||
* @throws Postman_Zend_Mail_Transport_Exception if mail is empty
|
||||
*/
|
||||
public function send(Postman_Zend_Mail $mail)
|
||||
{
|
||||
$this->_isMultipart = false;
|
||||
$this->_mail = $mail;
|
||||
$this->_parts = $mail->getParts();
|
||||
$mime = $mail->getMime();
|
||||
|
||||
// Build body content
|
||||
$this->_buildBody();
|
||||
|
||||
// Determine number of parts and boundary
|
||||
$count = count($this->_parts);
|
||||
$boundary = null;
|
||||
if ($count < 1) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Transport_Exception
|
||||
*/
|
||||
require_once 'Exception.php';
|
||||
throw new Postman_Zend_Mail_Transport_Exception('Empty mail cannot be sent');
|
||||
}
|
||||
|
||||
if ($count > 1) {
|
||||
// Multipart message; create new MIME object and boundary
|
||||
$mime = new Postman_Zend_Mime($this->_mail->getMimeBoundary());
|
||||
$boundary = $mime->boundary();
|
||||
} elseif ($this->_isMultipart) {
|
||||
// multipart/alternative -- grab boundary
|
||||
$boundary = $this->_parts[0]->boundary;
|
||||
}
|
||||
|
||||
// Determine recipients, and prepare headers
|
||||
$this->recipients = implode(',', $mail->getRecipients());
|
||||
$this->_prepareHeaders($this->_getHeaders($boundary));
|
||||
|
||||
// Create message body
|
||||
// This is done so that the same Postman_Zend_Mail object can be used in
|
||||
// multiple transports
|
||||
$message = new Postman_Zend_Mime_Message();
|
||||
$message->setParts($this->_parts);
|
||||
$message->setMime($mime);
|
||||
$this->body = $message->generateMessage($this->EOL);
|
||||
|
||||
// Send to transport!
|
||||
$this->_sendMail();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Transport
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Exception
|
||||
*/
|
||||
// require_once 'Zend/Mail/Exception.php';
|
||||
|
||||
|
||||
/**
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Transport
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Postman_Zend_Mail_Transport_Exception extends Postman_Zend_Mail_Exception
|
||||
{}
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Transport
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Transport_Abstract
|
||||
*/
|
||||
require_once 'Zend/Mail/Transport/Abstract.php';
|
||||
|
||||
|
||||
/**
|
||||
* File transport
|
||||
*
|
||||
* Class for saving outgoing emails in filesystem
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Transport
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Postman_Zend_Mail_Transport_File extends Postman_Zend_Mail_Transport_Abstract
|
||||
{
|
||||
/**
|
||||
* Target directory for saving sent email messages
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_path;
|
||||
|
||||
/**
|
||||
* Callback function generating a file name
|
||||
*
|
||||
* @var string|array
|
||||
*/
|
||||
protected $_callback;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param array|Postman_Zend_Config $options OPTIONAL (Default: null)
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($options = null)
|
||||
{
|
||||
if ($options instanceof Postman_Zend_Config) {
|
||||
$options = $options->toArray();
|
||||
} elseif (!is_array($options)) {
|
||||
$options = array();
|
||||
}
|
||||
|
||||
// Making sure we have some defaults to work with
|
||||
if (!isset($options['path'])) {
|
||||
$options['path'] = sys_get_temp_dir();
|
||||
}
|
||||
if (!isset($options['callback'])) {
|
||||
$options['callback'] = array($this, 'defaultCallback');
|
||||
}
|
||||
|
||||
$this->setOptions($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets options
|
||||
*
|
||||
* @param array $options
|
||||
* @return void
|
||||
*/
|
||||
public function setOptions(array $options)
|
||||
{
|
||||
if (isset($options['path']) && is_dir($options['path'])) {
|
||||
$this->_path = $options['path'];
|
||||
}
|
||||
if (isset($options['callback']) && is_callable($options['callback'])) {
|
||||
$this->_callback = $options['callback'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves e-mail message to a file
|
||||
*
|
||||
* @return void
|
||||
* @throws Postman_Zend_Mail_Transport_Exception on not writable target directory
|
||||
* @throws Postman_Zend_Mail_Transport_Exception on file_put_contents() failure
|
||||
*/
|
||||
protected function _sendMail()
|
||||
{
|
||||
$file = $this->_path . DIRECTORY_SEPARATOR . call_user_func($this->_callback, $this);
|
||||
|
||||
if (!is_writable(dirname($file))) {
|
||||
require_once 'Zend/Mail/Transport/Exception.php';
|
||||
throw new Postman_Zend_Mail_Transport_Exception(sprintf(
|
||||
'Target directory "%s" does not exist or is not writable',
|
||||
dirname($file)
|
||||
));
|
||||
}
|
||||
|
||||
$email = $this->header . $this->EOL . $this->body;
|
||||
|
||||
if (!file_put_contents($file, $email)) {
|
||||
require_once 'Zend/Mail/Transport/Exception.php';
|
||||
throw new Postman_Zend_Mail_Transport_Exception('Unable to send mail');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Default callback for generating filenames
|
||||
*
|
||||
* @param Postman_Zend_Mail_Transport_File File transport instance
|
||||
* @return string
|
||||
*/
|
||||
public function defaultCallback($transport)
|
||||
{
|
||||
return 'ZendMail_' . $_SERVER['REQUEST_TIME'] . '_' . mt_rand() . '.tmp';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Transport
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Transport_Abstract
|
||||
*/
|
||||
// require_once 'Zend/Mail/Transport/Abstract.php';
|
||||
|
||||
|
||||
/**
|
||||
* Class for sending eMails via the PHP internal mail() function
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Transport
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Postman_Zend_Mail_Transport_Sendmail extends Postman_Zend_Mail_Transport_Abstract
|
||||
{
|
||||
/**
|
||||
* Subject
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
public $subject = null;
|
||||
|
||||
|
||||
/**
|
||||
* Config options for sendmail parameters
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $parameters;
|
||||
|
||||
/**
|
||||
* EOL character string
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
public $EOL = PHP_EOL;
|
||||
|
||||
/**
|
||||
* error information
|
||||
* @var string
|
||||
*/
|
||||
protected $_errstr;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string|array|Postman_Zend_Config $parameters OPTIONAL (Default: null)
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($parameters = null)
|
||||
{
|
||||
if ($parameters instanceof Postman_Zend_Config) {
|
||||
$parameters = $parameters->toArray();
|
||||
}
|
||||
|
||||
if (is_array($parameters)) {
|
||||
$parameters = implode(' ', $parameters);
|
||||
}
|
||||
|
||||
$this->parameters = $parameters;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send mail using PHP native mail()
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
* @throws Postman_Zend_Mail_Transport_Exception if parameters is set
|
||||
* but not a string
|
||||
* @throws Postman_Zend_Mail_Transport_Exception on mail() failure
|
||||
*/
|
||||
public function _sendMail()
|
||||
{
|
||||
if ($this->parameters === null) {
|
||||
set_error_handler(array($this, '_handleMailErrors'));
|
||||
$result = mail(
|
||||
$this->recipients,
|
||||
$this->_mail->getSubject(),
|
||||
$this->body,
|
||||
$this->header);
|
||||
restore_error_handler();
|
||||
} else {
|
||||
if(!is_string($this->parameters)) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Transport_Exception
|
||||
*
|
||||
* Exception is thrown here because
|
||||
* $parameters is a public property
|
||||
*/
|
||||
// require_once 'Zend/Mail/Transport/Exception.php';
|
||||
throw new Postman_Zend_Mail_Transport_Exception(
|
||||
'Parameters were set but are not a string'
|
||||
);
|
||||
}
|
||||
|
||||
set_error_handler(array($this, '_handleMailErrors'));
|
||||
$result = mail(
|
||||
$this->recipients,
|
||||
$this->_mail->getSubject(),
|
||||
$this->body,
|
||||
$this->header,
|
||||
$this->parameters);
|
||||
restore_error_handler();
|
||||
}
|
||||
|
||||
if ($this->_errstr !== null || !$result) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Transport_Exception
|
||||
*/
|
||||
// require_once 'Zend/Mail/Transport/Exception.php';
|
||||
throw new Postman_Zend_Mail_Transport_Exception('Unable to send mail. ' . $this->_errstr);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Format and fix headers
|
||||
*
|
||||
* mail() uses its $to and $subject arguments to set the To: and Subject:
|
||||
* headers, respectively. This method strips those out as a sanity check to
|
||||
* prevent duplicate header entries.
|
||||
*
|
||||
* @access protected
|
||||
* @param array $headers
|
||||
* @return void
|
||||
* @throws Postman_Zend_Mail_Transport_Exception
|
||||
*/
|
||||
protected function _prepareHeaders($headers)
|
||||
{
|
||||
if (!$this->_mail) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Transport_Exception
|
||||
*/
|
||||
// require_once 'Zend/Mail/Transport/Exception.php';
|
||||
throw new Postman_Zend_Mail_Transport_Exception('_prepareHeaders requires a registered Postman_Zend_Mail object');
|
||||
}
|
||||
|
||||
// mail() uses its $to parameter to set the To: header, and the $subject
|
||||
// parameter to set the Subject: header. We need to strip them out.
|
||||
if (0 === strpos(PHP_OS, 'WIN')) {
|
||||
// If the current recipients list is empty, throw an error
|
||||
if (empty($this->recipients)) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Transport_Exception
|
||||
*/
|
||||
// require_once 'Zend/Mail/Transport/Exception.php';
|
||||
throw new Postman_Zend_Mail_Transport_Exception('Missing To addresses');
|
||||
}
|
||||
} else {
|
||||
// All others, simply grab the recipients and unset the To: header
|
||||
if (!isset($headers['To'])) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Transport_Exception
|
||||
*/
|
||||
// require_once 'Zend/Mail/Transport/Exception.php';
|
||||
throw new Postman_Zend_Mail_Transport_Exception('Missing To header');
|
||||
}
|
||||
|
||||
unset($headers['To']['append']);
|
||||
$this->recipients = implode(',', $headers['To']);
|
||||
}
|
||||
|
||||
// Remove recipient header
|
||||
unset($headers['To']);
|
||||
|
||||
// Remove subject header, if present
|
||||
if (isset($headers['Subject'])) {
|
||||
unset($headers['Subject']);
|
||||
}
|
||||
|
||||
// Prepare headers
|
||||
parent::_prepareHeaders($headers);
|
||||
|
||||
// Fix issue with empty blank line ontop when using Sendmail Trnasport
|
||||
$this->header = rtrim($this->header);
|
||||
}
|
||||
|
||||
/**
|
||||
* Temporary error handler for PHP native mail().
|
||||
*
|
||||
* @param int $errno
|
||||
* @param string $errstr
|
||||
* @param string $errfile
|
||||
* @param string $errline
|
||||
* @param array $errcontext
|
||||
* @return true
|
||||
*/
|
||||
public function _handleMailErrors($errno, $errstr, $errfile = null, $errline = null, ?array $errcontext = null)
|
||||
{
|
||||
$this->_errstr = $errstr;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,247 @@
|
||||
<?php
|
||||
/**
|
||||
* Zend Framework
|
||||
*
|
||||
* LICENSE
|
||||
*
|
||||
* This source file is subject to the new BSD license that is bundled
|
||||
* with this package in the file LICENSE.txt.
|
||||
* It is also available through the world-wide-web at this URL:
|
||||
* http://framework.zend.com/license/new-bsd
|
||||
* If you did not receive a copy of the license and are unable to
|
||||
* obtain it through the world-wide-web, please send an email
|
||||
* to license@zend.com so we can send you a copy immediately.
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Transport
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
* @version $Id$
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mime
|
||||
*/
|
||||
// require_once 'Zend/Mime.php';
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Protocol_Smtp
|
||||
*/
|
||||
// require_once 'Zend/Mail/Protocol/Smtp.php';
|
||||
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Transport_Abstract
|
||||
*/
|
||||
// require_once 'Zend/Mail/Transport/Abstract.php';
|
||||
|
||||
|
||||
/**
|
||||
* SMTP connection object
|
||||
*
|
||||
* Loads an instance of Postman_Zend_Mail_Protocol_Smtp and forwards smtp transactions
|
||||
*
|
||||
* @category Zend
|
||||
* @package Postman_Zend_Mail
|
||||
* @subpackage Transport
|
||||
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
|
||||
* @license http://framework.zend.com/license/new-bsd New BSD License
|
||||
*/
|
||||
class Postman_Zend_Mail_Transport_Smtp extends Postman_Zend_Mail_Transport_Abstract
|
||||
{
|
||||
/**
|
||||
* EOL character string used by transport
|
||||
* @var string
|
||||
* @access public
|
||||
*/
|
||||
public $EOL = "\n";
|
||||
|
||||
/**
|
||||
* Remote smtp hostname or i.p.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_host;
|
||||
|
||||
|
||||
/**
|
||||
* Port number
|
||||
*
|
||||
* @var integer|null
|
||||
*/
|
||||
protected $_port;
|
||||
|
||||
|
||||
/**
|
||||
* Local client hostname or i.p.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_name = 'localhost';
|
||||
|
||||
|
||||
/**
|
||||
* Authentication type OPTIONAL
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_auth;
|
||||
|
||||
|
||||
/**
|
||||
* Config options for authentication
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_config;
|
||||
|
||||
|
||||
/**
|
||||
* Instance of Postman_Zend_Mail_Protocol_Smtp
|
||||
*
|
||||
* @var Postman_Zend_Mail_Protocol_Smtp
|
||||
*/
|
||||
protected $_connection;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $host OPTIONAL (Default: 127.0.0.1)
|
||||
* @param array|null $config OPTIONAL (Default: null)
|
||||
* @return void
|
||||
*
|
||||
* @todo Someone please make this compatible
|
||||
* with the SendMail transport class.
|
||||
*/
|
||||
public function __construct($host = '127.0.0.1', Array $config = array())
|
||||
{
|
||||
if (isset($config['name'])) {
|
||||
$this->_name = $config['name'];
|
||||
} else {
|
||||
$this->_name = PostmanUtils::getServerName();
|
||||
}
|
||||
|
||||
if (isset($config['port'])) {
|
||||
$this->_port = $config['port'];
|
||||
}
|
||||
|
||||
if (isset($config['auth'])) {
|
||||
$this->_auth = $config['auth'];
|
||||
}
|
||||
|
||||
$this->_host = $host;
|
||||
$this->_config = $config;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Class destructor to ensure all open connections are closed
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __destruct()
|
||||
{
|
||||
if ($this->_connection instanceof Postman_Zend_Mail_Protocol_Smtp) {
|
||||
try {
|
||||
$this->_connection->quit();
|
||||
} catch (Postman_Zend_Mail_Protocol_Exception $e) {
|
||||
// ignore
|
||||
}
|
||||
$this->_connection->disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the connection protocol instance
|
||||
*
|
||||
* @param Postman_Zend_Mail_Protocol_Abstract $client
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setConnection(Postman_Zend_Mail_Protocol_Abstract $connection)
|
||||
{
|
||||
$this->_connection = $connection;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the connection protocol instance
|
||||
*
|
||||
* @return Postman_Zend_Mail_Protocol|null
|
||||
*/
|
||||
public function getConnection()
|
||||
{
|
||||
return $this->_connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an email via the SMTP connection protocol
|
||||
*
|
||||
* The connection via the protocol adapter is made just-in-time to allow a
|
||||
* developer to add a custom adapter if required before mail is sent.
|
||||
*
|
||||
* @return void
|
||||
* @todo Rename this to sendMail, it's a public method...
|
||||
*/
|
||||
public function _sendMail()
|
||||
{
|
||||
// If sending multiple messages per session use existing adapter
|
||||
if (!($this->_connection instanceof Postman_Zend_Mail_Protocol_Smtp)) {
|
||||
// Check if authentication is required and determine required class
|
||||
$connectionClass = 'Postman_Zend_Mail_Protocol_Smtp';
|
||||
if ($this->_auth) {
|
||||
$connectionClass .= '_Auth_' . ucwords($this->_auth);
|
||||
}
|
||||
if (!class_exists($connectionClass)) {
|
||||
// require_once 'Zend/Loader.php';
|
||||
// Postman_Zend_Loader::loadClass($connectionClass);
|
||||
}
|
||||
$this->setConnection(new $connectionClass($this->_host, $this->_port, $this->_config));
|
||||
$this->_connection->connect();
|
||||
$this->_connection->helo($this->_name);
|
||||
} else {
|
||||
// Reset connection to ensure reliable transaction
|
||||
$this->_connection->rset();
|
||||
}
|
||||
|
||||
// Set sender email address
|
||||
$this->_connection->mail($this->_mail->getReturnPath());
|
||||
|
||||
// Set recipient forward paths
|
||||
foreach ($this->_mail->getRecipients() as $recipient) {
|
||||
$this->_connection->rcpt($recipient);
|
||||
}
|
||||
|
||||
// Issue DATA command to client
|
||||
$this->_connection->data($this->header . Postman_Zend_Mime::LINEEND . $this->body);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format and fix headers
|
||||
*
|
||||
* Some SMTP servers do not strip BCC headers. Most clients do it themselves as do we.
|
||||
*
|
||||
* @access protected
|
||||
* @param array $headers
|
||||
* @return void
|
||||
* @throws Postman_Zend_Transport_Exception
|
||||
*/
|
||||
protected function _prepareHeaders($headers)
|
||||
{
|
||||
if (!$this->_mail) {
|
||||
/**
|
||||
* @see Postman_Zend_Mail_Transport_Exception
|
||||
*/
|
||||
// require_once 'Zend/Mail/Transport/Exception.php';
|
||||
throw new Postman_Zend_Mail_Transport_Exception('_prepareHeaders requires a registered Postman_Zend_Mail object');
|
||||
}
|
||||
|
||||
unset($headers['Bcc']);
|
||||
|
||||
// Prepare headers
|
||||
parent::_prepareHeaders($headers);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user