forked from LiveCarta/LiveCartaWP
Changed source root directory
This commit is contained in:
474
html/wp-content/plugins/post-smtp/Postman/PostmanWpMail.php
Normal file
474
html/wp-content/plugins/post-smtp/Postman/PostmanWpMail.php
Normal file
@@ -0,0 +1,474 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
if ( ! class_exists( 'PostmanWpMail' ) ) {
|
||||
|
||||
/**
|
||||
* Moved this code into a class so it could be used by both wp_mail() and PostmanSendTestEmailController
|
||||
*
|
||||
* @author jasonhendriks
|
||||
*/
|
||||
class PostmanWpMail {
|
||||
private $exception;
|
||||
private $transcript;
|
||||
private $totalTime;
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* Load the dependencies
|
||||
*/
|
||||
public function init() {
|
||||
$this->logger = new PostmanLogger( get_class( $this ) );
|
||||
require_once 'Postman-Mail/PostmanMessage.php';
|
||||
require_once 'Postman-Email-Log/PostmanEmailLogService.php';
|
||||
require_once 'Postman-Mail/PostmanMailEngine.php';
|
||||
require_once 'Postman-Auth/PostmanAuthenticationManagerFactory.php';
|
||||
require_once 'PostmanState.php';
|
||||
|
||||
PostmanEmailLogService::getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* This methods follows the wp_mail function interface, but implements it Postman-style.
|
||||
* Exceptions are held for later inspection.
|
||||
* An instance of PostmanState updates the success/fail tally.
|
||||
*
|
||||
* @param mixed $to
|
||||
* @param mixed $subject
|
||||
* @param mixed $body
|
||||
* @param mixed $headers
|
||||
* @param mixed $attachments
|
||||
* @return boolean
|
||||
*/
|
||||
public function send( $to, $subject, $message, $headers = '', $attachments = array() ) {
|
||||
|
||||
// initialize for sending
|
||||
$this->init();
|
||||
|
||||
// build the message
|
||||
$postmanMessage = $this->processWpMailCall( $to, $subject, $message, $headers, $attachments );
|
||||
|
||||
// build the email log entry
|
||||
$log = new PostmanEmailLog();
|
||||
|
||||
// Merge forced recipients with original $to for logging
|
||||
$options = PostmanOptions::getInstance();
|
||||
$forcedTo = $options->getForcedToRecipients();
|
||||
$allRecipients = array();
|
||||
|
||||
// Add original recipients
|
||||
if ( is_array( $to ) ) {
|
||||
$allRecipients = array_merge( $allRecipients, $to );
|
||||
} elseif ( ! empty( $to ) ) {
|
||||
// Split comma-separated string into array
|
||||
$allRecipients = array_merge( $allRecipients, array_map( 'trim', explode( ',', $to ) ) );
|
||||
}
|
||||
|
||||
// Add forced recipients if set
|
||||
if ( ! empty( $forcedTo ) ) {
|
||||
// Split comma-separated string into array
|
||||
$forcedRecipients = array_map( 'trim', explode( ',', $forcedTo ) );
|
||||
$allRecipients = array_merge( $allRecipients, $forcedRecipients );
|
||||
}
|
||||
|
||||
// Remove duplicates and empty values, then convert back to comma-separated string
|
||||
$allRecipients = array_unique( array_filter( $allRecipients ) );
|
||||
$log->originalTo = implode( ', ', $allRecipients );
|
||||
|
||||
$log->originalSubject = $subject;
|
||||
$log->originalMessage = $message;
|
||||
$log->originalHeaders = $headers;
|
||||
|
||||
// send the message and return the result
|
||||
return $this->sendMessage( $postmanMessage, $log );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param PostmanMessage $message
|
||||
* @return PostmanMessage
|
||||
*/
|
||||
private function apply_default_headers( $message ) {
|
||||
$headers[] = 'Message-ID: ' . $this->createMessageId();
|
||||
$message->addHeaders($headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the Message-ID
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function createMessageId() {
|
||||
|
||||
$id = md5(uniqid(time()));
|
||||
|
||||
if (isset($_SERVER["SERVER_NAME"])) {
|
||||
$hostName = sanitize_text_field($_SERVER["SERVER_NAME"]);
|
||||
} else {
|
||||
$hostName = php_uname('n');
|
||||
}
|
||||
|
||||
return $id . '@' . str_replace('www.', '', $hostName);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a PostmanMessage based on the WordPress wp_mail parameters
|
||||
*
|
||||
* @param mixed $to
|
||||
* @param mixed $subject
|
||||
* @param mixed $message
|
||||
* @param mixed $headers
|
||||
* @param mixed $attachments
|
||||
*/
|
||||
public function processWpMailCall( $to, $subject, $message, $headers, $attachments ) {
|
||||
$this->logger->trace( 'wp_mail parameters before applying WordPress wp_mail filter:' );
|
||||
$this->traceParameters( $to, $subject, $message, $headers, $attachments );
|
||||
|
||||
/**
|
||||
* Filter the wp_mail() arguments.
|
||||
*
|
||||
* @since 1.5.4
|
||||
*
|
||||
* @param array $args
|
||||
* A compacted array of wp_mail() arguments, including the "to" email,
|
||||
* subject, message, headers, and attachments values.
|
||||
*/
|
||||
$atts = apply_filters( 'wp_mail', compact( 'to', 'subject', 'message', 'headers', 'attachments' ) );
|
||||
|
||||
if ( isset( $atts ['to'] ) ) {
|
||||
$to = $atts ['to'];
|
||||
}
|
||||
|
||||
if ( isset( $atts ['subject'] ) ) {
|
||||
$subject = $atts ['subject'];
|
||||
}
|
||||
|
||||
if ( isset( $atts ['message'] ) ) {
|
||||
$message = $atts ['message'];
|
||||
}
|
||||
|
||||
if ( isset( $atts ['headers'] ) ) {
|
||||
$headers = $atts ['headers'];
|
||||
}
|
||||
|
||||
if ( isset( $atts ['attachments'] ) ) {
|
||||
$attachments = $atts ['attachments'];
|
||||
}
|
||||
|
||||
if ( ! is_array( $attachments ) ) {
|
||||
$attachments = explode( "\n", str_replace( "\r\n", "\n", $attachments ) );
|
||||
}
|
||||
|
||||
$this->logger->trace( 'wp_mail parameters after applying WordPress wp_mail filter:' );
|
||||
$this->traceParameters( $to, $subject, $message, $headers, $attachments );
|
||||
|
||||
// Postman API: register the response hook
|
||||
add_filter( 'postman_wp_mail_result', array(
|
||||
$this,
|
||||
'postman_wp_mail_result',
|
||||
) );
|
||||
|
||||
// create the message
|
||||
$postmanMessage = $this->createNewMessage();
|
||||
$this->populateMessageFromWpMailParams( $postmanMessage, $to, $subject, $message, $headers, $attachments );
|
||||
|
||||
// return the message
|
||||
return $postmanMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of PostmanMessage with a pre-set From and Reply-To
|
||||
*
|
||||
* @return PostmanMessage
|
||||
*/
|
||||
public function createNewMessage() {
|
||||
$message = new PostmanMessage();
|
||||
$options = PostmanOptions::getInstance();
|
||||
// the From is set now so that it can be overridden
|
||||
$transport = PostmanTransportRegistry::getInstance()->getActiveTransport();
|
||||
if ( $transport !== null ) {
|
||||
$fromEmail = $transport->getFromEmailAddress();
|
||||
$fromName = $transport->getFromName();
|
||||
} else {
|
||||
// fallback to options or defaults if transport is null
|
||||
$fromEmail = $options->getMessageSenderEmail();
|
||||
$fromName = $options->getMessageSenderName();
|
||||
}
|
||||
$message->setFrom( $fromEmail, $fromName );
|
||||
// the Reply-To is set now so that it can be overridden
|
||||
$message->setReplyTo( $options->getReplyTo() );
|
||||
$message->setCharset( get_bloginfo( 'charset' ) );
|
||||
return $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenient place for any code to inject a constructed PostmanMessage
|
||||
* (for example, from MyMail)
|
||||
*
|
||||
* The body parts may be set already at this time.
|
||||
*
|
||||
* @param PostmanMessage $message
|
||||
* @return boolean
|
||||
*/
|
||||
public function sendMessage( PostmanMessage $message, PostmanEmailLog $log ) {
|
||||
|
||||
$this->apply_default_headers( $message );
|
||||
|
||||
// get the Options and AuthToken
|
||||
$options = PostmanOptions::getInstance();
|
||||
$authorizationToken = PostmanOAuthToken::getInstance();
|
||||
|
||||
// get the transport and create the transportConfig and engine
|
||||
$transport = PostmanTransportRegistry::getInstance()->getActiveTransport();
|
||||
|
||||
// create the Mail Engine
|
||||
$engine = $transport->createMailEngine();
|
||||
|
||||
// add plugin-specific attributes to PostmanMessage
|
||||
$message->addHeaders( $options->getAdditionalHeaders() );
|
||||
$message->addTo( $options->getForcedToRecipients() );
|
||||
$message->addCc( $options->getForcedCcRecipients() );
|
||||
$message->addBcc( $options->getForcedBccRecipients() );
|
||||
|
||||
// apply the WordPress filters
|
||||
// may impact the from address, from email, charset and content-type
|
||||
$message->applyFilters();
|
||||
|
||||
// create the body parts (if they are both missing)
|
||||
if ( $message->isBodyPartsEmpty() ) {
|
||||
$message->createBodyParts();
|
||||
}
|
||||
|
||||
// is this a test run?
|
||||
$testMode = apply_filters( 'postman_test_email', false );
|
||||
if ( $this->logger->isDebug() ) {
|
||||
$this->logger->debug( 'testMode=' . $testMode );
|
||||
}
|
||||
|
||||
// start the clock
|
||||
$startTime = microtime( true ) * 1000;
|
||||
|
||||
try {
|
||||
|
||||
// prepare the message
|
||||
$message->validate( $transport );
|
||||
|
||||
// send the message
|
||||
if ( $options->getRunMode() == PostmanOptions::RUN_MODE_PRODUCTION ) {
|
||||
if ( $transport->isLockingRequired() ) {
|
||||
PostmanUtils::lock();
|
||||
// may throw an exception attempting to contact the OAuth2 provider
|
||||
$this->ensureAuthtokenIsUpdated( $transport, $options, $authorizationToken );
|
||||
}
|
||||
|
||||
$this->logger->debug( 'Sending mail' );
|
||||
|
||||
// may throw an exception attempting to contact the SMTP server
|
||||
/**
|
||||
* Filters to send email or not
|
||||
*
|
||||
* @param bool $send_email
|
||||
* @since 2.5.0
|
||||
* @version 1.0.0
|
||||
*/
|
||||
if ( $send_email = apply_filters( 'post_smtp_do_send_email', true ) && apply_filters( 'post_smtp_send_email', true ) ) {
|
||||
|
||||
$engine->send( $message );
|
||||
|
||||
} else {
|
||||
$this->transcript = 'Bypassed By MailControl For Post SMTP';
|
||||
}
|
||||
|
||||
// increment the success counter, unless we are just tesitng
|
||||
if ( ! $testMode ) {
|
||||
PostmanState::getInstance()->incrementSuccessfulDelivery();
|
||||
}
|
||||
}
|
||||
|
||||
// clean up
|
||||
$this->postSend( $engine, $startTime, $options, $transport );
|
||||
|
||||
/**
|
||||
* Do stuff after successful delivery
|
||||
*/
|
||||
if ($transport !== null) {
|
||||
do_action( 'post_smtp_on_success', $log, $message, $engine->getTranscript(), $transport );
|
||||
} else {
|
||||
if ($this->logger) {
|
||||
$this->logger->warning('Transport is null, skipping post_smtp_on_success action to avoid fatal error.');
|
||||
}
|
||||
}
|
||||
// return successful
|
||||
return true;
|
||||
} catch ( Exception $e ) {
|
||||
// save the error for later
|
||||
$this->exception = $e;
|
||||
|
||||
// write the error to the PHP log
|
||||
$this->logger->error( get_class( $e ) . ' code=' . $e->getCode() . ' message=' . trim( $e->getMessage() ) );
|
||||
|
||||
// increment the failure counter, unless we are just tesitng
|
||||
if ( ! $testMode && $options->getRunMode() == PostmanOptions::RUN_MODE_PRODUCTION ) {
|
||||
PostmanState::getInstance()->incrementFailedDelivery();
|
||||
}
|
||||
|
||||
// clean up
|
||||
$this->postSend( $engine, $startTime, $options, $transport );
|
||||
|
||||
|
||||
/**
|
||||
* Do stuff after failed delivery
|
||||
*/
|
||||
if ($transport !== null) {
|
||||
do_action( 'post_smtp_on_failed', $log, $message, $engine->getTranscript(), $transport, $e->getMessage() );
|
||||
} else {
|
||||
if ($this->logger) {
|
||||
$this->logger->warning('Transport is null, skipping post_smtp_on_failed action to avoid fatal error.');
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback
|
||||
if ( $this->fallback( $log, $message, $options ) ) {
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
$mail_error_data = array(
|
||||
'to' => $message->getToRecipients(),
|
||||
'subject' => $message->getSubject(),
|
||||
'message' => $message->getBody(),
|
||||
'headers' => $message->getHeaders(),
|
||||
'attachments' => $message->getAttachments()
|
||||
);
|
||||
$mail_error_data['phpmailer_exception_code'] = $e->getCode();
|
||||
|
||||
do_action( 'wp_mail_failed', new WP_Error( 'wp_mail_failed', $e->getMessage(), $mail_error_data ) );
|
||||
|
||||
// return failure
|
||||
if ( PostmanOptions::getInstance()->getSmtpMailer() == 'phpmailer' ) {
|
||||
throw new phpmailerException($e->getMessage(), $e->getCode());
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private function fallback( $log, $postMessage,$options ) {
|
||||
|
||||
if ( ! $options->is_fallback && $options->getFallbackIsEnabled() && $options->getFallbackIsEnabled() == 'yes' ) {
|
||||
|
||||
$options->is_fallback = true;
|
||||
|
||||
$status = $this->sendMessage( $postMessage, $log );
|
||||
|
||||
$options->is_fallback = false;
|
||||
|
||||
return $status;
|
||||
|
||||
} else {
|
||||
$options->is_fallback = false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean up after sending the mail
|
||||
*
|
||||
* @param PostmanZendMailEngine $engine
|
||||
* @param mixed $startTime
|
||||
*/
|
||||
private function postSend( PostmanMailEngine $engine, $startTime, PostmanOptions $options, PostmanModuleTransport $transport ) {
|
||||
// save the transcript
|
||||
$this->transcript = $engine->getTranscript();
|
||||
|
||||
// log the transcript
|
||||
if ( $this->logger->isTrace() ) {
|
||||
$this->logger->trace( 'Transcript:' );
|
||||
$this->logger->trace( $this->transcript );
|
||||
}
|
||||
|
||||
// delete the semaphore
|
||||
if ( $transport->isLockingRequired() ) {
|
||||
PostmanUtils::unlock();
|
||||
}
|
||||
|
||||
// stop the clock
|
||||
$endTime = microtime( true ) * 1000;
|
||||
$this->totalTime = $endTime - $startTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the result of the last call to send()
|
||||
*
|
||||
* @return multitype:Exception NULL
|
||||
*/
|
||||
function postman_wp_mail_result() {
|
||||
$result = array(
|
||||
'time' => $this->totalTime,
|
||||
'exception' => $this->exception,
|
||||
'transcript' => $this->transcript,
|
||||
);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
private function ensureAuthtokenIsUpdated( PostmanModuleTransport $transport, PostmanOptions $options, PostmanOAuthToken $authorizationToken ) {
|
||||
assert( ! empty( $transport ) );
|
||||
assert( ! empty( $options ) );
|
||||
assert( ! empty( $authorizationToken ) );
|
||||
// ensure the token is up-to-date
|
||||
$this->logger->debug( 'Ensuring Access Token is up-to-date' );
|
||||
// interact with the Authentication Manager
|
||||
$wpMailAuthManager = PostmanAuthenticationManagerFactory::getInstance()->createAuthenticationManager();
|
||||
if ( $wpMailAuthManager->isAccessTokenExpired() ) {
|
||||
$this->logger->debug( 'Access Token has expired, attempting refresh' );
|
||||
$wpMailAuthManager->refreshToken();
|
||||
$authorizationToken->save();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Aggregates all the content into a Message to be sent to the MailEngine
|
||||
*
|
||||
* @param mixed $to
|
||||
* @param mixed $subject
|
||||
* @param mixed $body
|
||||
* @param mixed $headers
|
||||
* @param mixed $attachments
|
||||
*/
|
||||
private function populateMessageFromWpMailParams( PostmanMessage $message, $to, $subject, $body, $headers, $attachments ) {
|
||||
$message->addHeaders( $headers );
|
||||
$message->setBody( $body );
|
||||
$message->setSubject( $subject );
|
||||
$message->addTo( $to );
|
||||
$message->setAttachments( $attachments );
|
||||
return $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trace the parameters to aid in debugging
|
||||
*
|
||||
* @param mixed $to
|
||||
* @param mixed $subject
|
||||
* @param mixed $body
|
||||
* @param mixed $headers
|
||||
* @param mixed $attachments
|
||||
*/
|
||||
private function traceParameters( $to, $subject, $message, $headers, $attachments ) {
|
||||
$this->logger->trace( 'to:' );
|
||||
$this->logger->trace( $to );
|
||||
$this->logger->trace( 'subject:' );
|
||||
$this->logger->trace( $subject );
|
||||
$this->logger->trace( 'headers:' );
|
||||
$this->logger->trace( $headers );
|
||||
$this->logger->trace( 'attachments:' );
|
||||
$this->logger->trace( $attachments );
|
||||
$this->logger->trace( 'message:' );
|
||||
$this->logger->trace( $message );
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user