summaryrefslogtreecommitdiff
path: root/Postman/PostmanWpMail.php
diff options
context:
space:
mode:
Diffstat (limited to 'Postman/PostmanWpMail.php')
-rw-r--r--Postman/PostmanWpMail.php340
1 files changed, 340 insertions, 0 deletions
diff --git a/Postman/PostmanWpMail.php b/Postman/PostmanWpMail.php
new file mode 100644
index 0000000..874a338
--- /dev/null
+++ b/Postman/PostmanWpMail.php
@@ -0,0 +1,340 @@
+<?php
+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';
+ }
+
+ /**
+ * 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 unknown $to
+ * @param unknown $subject
+ * @param unknown $body
+ * @param unknown $headers
+ * @param unknown $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 ();
+ $log->originalTo = $to;
+ $log->originalSubject = $subject;
+ $log->originalMessage = $message;
+ $log->originalHeaders = $headers;
+
+ // send the message and return the result
+ return $this->sendMessage ( $postmanMessage, $log );
+ }
+
+ /**
+ * Builds a PostmanMessage based on the WordPress wp_mail parameters
+ *
+ * @param unknown $to
+ * @param unknown $subject
+ * @param unknown $message
+ * @param unknown $headers
+ * @param unknown $attachments
+ */
+ private 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 ();
+ $message->setFrom ( $transport->getFromEmailAddress (), $transport->getFromName () );
+ // 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) {
+
+ // get the Options and AuthToken
+ $options = PostmanOptions::getInstance ();
+ $authorizationToken = PostmanOAuthToken::getInstance ();
+
+ // get the transport and create the transportConfig and engine
+ $transport = PostmanTransportRegistry::getInstance ()->getActiveTransport ();
+
+ // create the Mail Engine
+ $engine = $transport->createMailEngine ();
+
+ // add plugin-specific attributes to PostmanMessage
+ $message->addHeaders ( $options->getAdditionalHeaders () );
+ $message->addTo ( $options->getForcedToRecipients () );
+ $message->addCc ( $options->getForcedCcRecipients () );
+ $message->addBcc ( $options->getForcedBccRecipients () );
+
+ // apply the WordPress filters
+ // may impact the from address, from email, charset and content-type
+ $message->applyFilters ();
+
+ // create the body parts (if they are both missing)
+ if ($message->isBodyPartsEmpty ()) {
+ $message->createBodyParts ();
+ }
+
+ // is this a test run?
+ $testMode = apply_filters ( 'postman_test_email', false );
+ if ($this->logger->isDebug ()) {
+ $this->logger->debug ( 'testMode=' . $testMode );
+ }
+
+ // start the clock
+ $startTime = microtime ( true ) * 1000;
+
+ try {
+
+ // prepare the message
+ $message->validate ( $transport );
+
+ // send the message
+ if ($options->getRunMode () == PostmanOptions::RUN_MODE_PRODUCTION) {
+ if ($transport->isLockingRequired ()) {
+ PostmanUtils::lock ();
+ // may throw an exception attempting to contact the OAuth2 provider
+ $this->ensureAuthtokenIsUpdated ( $transport, $options, $authorizationToken );
+ }
+
+ $this->logger->debug ( 'Sending mail' );
+ // may throw an exception attempting to contact the SMTP server
+ $engine->send ( $message );
+
+ // increment the success counter, unless we are just tesitng
+ if (! $testMode) {
+ PostmanState::getInstance ()->incrementSuccessfulDelivery ();
+ }
+ }
+
+ // clean up
+ $this->postSend ( $engine, $startTime, $options, $transport );
+
+ if ($options->getRunMode () == PostmanOptions::RUN_MODE_PRODUCTION || $options->getRunMode () == PostmanOptions::RUN_MODE_LOG_ONLY) {
+ // log the successful delivery
+ PostmanEmailLogService::getInstance ()->writeSuccessLog ( $log, $message, $engine->getTranscript (), $transport );
+ }
+
+ // return successful
+ return true;
+ } catch ( Exception $e ) {
+ // save the error for later
+ $this->exception = $e;
+
+ // write the error to the PHP log
+ $this->logger->error ( get_class ( $e ) . ' code=' . $e->getCode () . ' message=' . trim ( $e->getMessage () ) );
+
+ // increment the failure counter, unless we are just tesitng
+ if (! $testMode && $options->getRunMode () == PostmanOptions::RUN_MODE_PRODUCTION) {
+ PostmanState::getInstance ()->incrementFailedDelivery ();
+ }
+
+ // clean up
+ $this->postSend ( $engine, $startTime, $options, $transport );
+
+ if ($options->getRunMode () == PostmanOptions::RUN_MODE_PRODUCTION || $options->getRunMode () == PostmanOptions::RUN_MODE_LOG_ONLY) {
+ // log the failed delivery
+ PostmanEmailLogService::getInstance ()->writeFailureLog ( $log, $message, $engine->getTranscript (), $transport, $e->getMessage () );
+ }
+
+ // return failure
+ return false;
+ }
+ }
+
+ /**
+ * Clean up after sending the mail
+ *
+ * @param PostmanZendMailEngine $engine
+ * @param unknown $startTime
+ */
+ private function postSend(PostmanMailEngine $engine, $startTime, PostmanOptions $options, PostmanModuleTransport $transport) {
+ // save the transcript
+ $this->transcript = $engine->getTranscript ();
+
+ // log the transcript
+ if ($this->logger->isTrace ()) {
+ $this->logger->trace ( 'Transcript:' );
+ $this->logger->trace ( $this->transcript );
+ }
+
+ // delete the semaphore
+ if ($transport->isLockingRequired ()) {
+ PostmanUtils::unlock ();
+ }
+
+ // stop the clock
+ $endTime = microtime ( true ) * 1000;
+ $this->totalTime = $endTime - $startTime;
+ }
+
+ /**
+ * 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 unknown $to
+ * @param unknown $subject
+ * @param unknown $body
+ * @param unknown $headers
+ * @param unknown $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 unknown $to
+ * @param unknown $subject
+ * @param unknown $body
+ * @param unknown $headers
+ * @param unknown $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 );
+ }
+ }
+} \ No newline at end of file