/** * Webhook parser class method for SendGrid. */ public function webhook_parser() { if (empty($_SERVER['HTTP_USER_AGENT']) || !empty($_SERVER['HTTP_USER_AGENT']) && 0 !== strpos($_SERVER['HTTP_USER_AGENT'], 'SendGrid')) { return; } if (empty($_POST) || empty($_POST['headers'])) { return; } bp_rbe_log('- SendGrid webhook received -'); // Format email headers to fit RBE spec. $temp = explode("\n", $_POST['headers']); $headers = array(); foreach ($temp as $line) { $colun = strpos($line, ':'); if (false === $colun) { continue; } $key = substr($line, 0, $colun); $headers[$key] = stripslashes(trim(substr($line, $colun + 1))); } $data = array('headers' => $headers, 'to_email' => BP_Reply_By_Email_Parser::get_header($headers, 'To'), 'from_email' => BP_Reply_By_Email_Parser::get_header($headers, 'From'), 'content' => $_POST['text'], 'subject' => $_POST['subject']); $parser = BP_Reply_By_Email_Parser::init($data, 1); if (is_wp_error($parser)) { do_action('bp_rbe_no_match', $parser, $data, 1, false); } bp_rbe_log('- Webhook parsing completed -'); die; }
/** * Webhook parser class method for Mandrill. */ public function webhook_parser() { if (empty($_SERVER['CONTENT_TYPE']) || !empty($_SERVER['CONTENT_TYPE']) && 'application/json' !== $_SERVER['CONTENT_TYPE']) { return; } if (!empty($_SERVER['HTTP_USER_AGENT']) && 'Postmark' !== $_SERVER['HTTP_USER_AGENT']) { return; } bp_rbe_log('- Postmark webhook received -'); $response = file_get_contents('php://input'); if (empty($response)) { bp_rbe_log('- Postmark webhook response failed -'); } $response = json_decode($response); // Format email headers to fit RBE spec. $headers = array(); foreach ($response->Headers as $header) { $headers[$header->Name] = $header->Value; } // Postmark separates parsed email headers; add them back for RBE parsing. $headers['From'] = $response->From; $headers['To'] = $response->To; $data = array('headers' => $headers, 'to_email' => $response->To, 'from_email' => $response->From, 'content' => $response->TextBody, 'subject' => $response->Subject); $parser = BP_Reply_By_Email_Parser::init($data, 1); if (is_wp_error($parser)) { do_action('bp_rbe_no_match', $parser, $data, 1, false); } bp_rbe_log('- Webhook parsing completed -'); die; }
/** * Webhook parser class method for SparkPost. */ public function webhook_parser() { if (empty($_SERVER['CONTENT_TYPE']) || !empty($_SERVER['CONTENT_TYPE']) && 'application/json' !== $_SERVER['CONTENT_TYPE']) { return; } if (false === isset($_SERVER['HTTP_X_MESSAGESYSTEMS_WEBHOOK_TOKEN'])) { return; } bp_rbe_log('- SparkPost webhook received -'); // SparkPost auth token verification. if (defined('BP_RBE_SPARKPOST_WEBHOOK_TOKEN') && !empty($_SERVER['HTTP_X_MESSAGESYSTEMS_WEBHOOK_TOKEN'])) { // Make sure auth token matches; if it doesn't, bail! if (constant('BP_RBE_SPARKPOST_WEBHOOK_TOKEN') !== $_SERVER['HTTP_X_MESSAGESYSTEMS_WEBHOOK_TOKEN']) { bp_rbe_log('SparkPost token verification failed.'); die; } } $response = file_get_contents('php://input'); if (empty($response)) { bp_rbe_log('- SporkPost webhook response failed -'); } $response = json_decode($response); $i = 1; foreach ($response as $item) { // Format email headers to fit RBE spec. $headers = array(); foreach ($item->msys->relay_message->content->headers as $header) { $headers = array_merge($headers, (array) $header); } $data = array('headers' => $headers, 'to_email' => $item->msys->relay_message->rcpt_to, 'from_email' => $item->msys->relay_message->friendly_from, 'content' => $item->msys->relay_message->content->text, 'subject' => $item->msys->relay_message->content->subject); $parser = BP_Reply_By_Email_Parser::init($data, $i); if (is_wp_error($parser)) { do_action('bp_rbe_no_match', $parser, $data, $i, false); } ++$i; } bp_rbe_log('- Webhook parsing completed -'); die; }
/** * Webhook parser class method for Mandrill. */ public function webhook_parser() { if (empty($_SERVER['HTTP_X_MANDRILL_SIGNATURE'])) { return; } if (!empty($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'Mandrill-Webhook/') === false) { return; } if (empty($_POST) || empty($_POST['mandrill_events'])) { return; } bp_rbe_log('- Mandrill webhook received -'); // mandrill signature verification if (defined('BP_RBE_MANDRILL_WEBHOOK_URL') && defined('BP_RBE_MANDRILL_WEBHOOK_KEY')) { $signed_data = constant('BP_RBE_MANDRILL_WEBHOOK_URL'); $signed_data .= 'mandrill_events'; $signed_data .= stripslashes($_POST['mandrill_events']); $webhook_key = constant('BP_RBE_MANDRILL_WEBHOOK_KEY'); $signature = base64_encode(hash_hmac('sha1', $signed_data, $webhook_key, true)); // check if generated signature matches Mandrill's if ($signature !== $_SERVER['HTTP_X_MANDRILL_SIGNATURE']) { bp_rbe_log('Mandrill signature verification failed.'); die; } } // get parsed content $response = json_decode(stripslashes($_POST['mandrill_events'])); // log JSON errors if present if (json_last_error() != JSON_ERROR_NONE) { switch (json_last_error()) { case JSON_ERROR_DEPTH: bp_rbe_log('json error: - Maximum stack depth exceeded'); break; case JSON_ERROR_STATE_MISMATCH: bp_rbe_log('json error: - Underflow or the modes mismatch'); break; case JSON_ERROR_CTRL_CHAR: bp_rbe_log('json error: - Unexpected control character found'); break; case JSON_ERROR_SYNTAX: bp_rbe_log('json error: - Syntax error, malformed JSON'); break; case JSON_ERROR_UTF8: bp_rbe_log('json error: - Malformed UTF-8 characters, possibly incorrectly encoded'); break; default: bp_rbe_log('json error: - Unknown error'); break; } die; // ready to start the parsing! } else { $i = 1; foreach ($response as $item) { $data = array('headers' => $item->msg->headers, 'to_email' => $item->msg->email, 'from_email' => $item->msg->from_email, 'content' => $item->msg->text, 'subject' => $item->msg->subject); $parser = BP_Reply_By_Email_Parser::init($data, $i); if (is_wp_error($parser)) { do_action('bp_rbe_no_match', $parser, $data, $i, false); } ++$i; } bp_rbe_log('- Webhook parsing completed -'); die; } }
/** * The main method we use to parse an IMAP inbox. */ public function run() { // $instance must be initialized before we go on! if (self::$instance === false) { return false; } // If safe mode isn't on, then let's set the execution time to unlimited if (!ini_get('safe_mode')) { set_time_limit(0); } // Try to connect $connect = $this->connect(); if (!$connect) { return false; } // Total duration we should keep the IMAP stream alive for in seconds $duration = bp_rbe_get_execution_time(); bp_rbe_log('--- Keep alive for ' . $duration / 60 . ' minutes ---'); bp_rbe_remove_imap_lock(); // Mark the current timestamp, mark the future time when we should close the IMAP connection; // Do our parsing until $future > $now; re-mark the timestamp at end of loop... rinse and repeat! for ($now = time(), $future = time() + $duration; $future > $now; $now = time()) { // Get number of messages $message_count = imap_num_msg($this->connection); // If there are messages in the inbox, let's start parsing! if ($message_count != 0) { // According to this: // http://www.php.net/manual/pl/function.imap-headerinfo.php#95012 // This speeds up rendering the email headers... could be wrong imap_headers($this->connection); bp_rbe_log('- Checking inbox -'); // Loop through each email message for ($i = 1; $i <= $message_count; ++$i) { // flush object cache if necessary // // we only flush the cache if the default object cache is in use // why? b/c the default object cache is only meant for single page loads and // since RBE runs in the background, we need to flush the object cache so WP // will do a direct DB query for the next data fetch if (!wp_using_ext_object_cache()) { wp_cache_flush(); } self::$html = false; $content = self::body_parser($this->connection, $i); $headers = $this->get_mail_headers($this->connection, $i); $data = array('headers' => $headers, 'to_email' => BP_Reply_By_Email_Parser::get_header($headers, 'To'), 'from_email' => BP_Reply_By_Email_Parser::get_header($headers, 'From'), 'content' => $content, 'is_html' => self::$html, 'subject' => imap_utf8(BP_Reply_By_Email_Parser::get_header($headers, 'Subject'))); $parser = BP_Reply_By_Email_Parser::init($data, $i); if (is_wp_error($parser)) { //do_action( 'bp_rbe_imap_no_match', $this->connection, $i, $headers, $parser->get_error_code() ); do_action('bp_rbe_no_match', $parser, $data, $i, $this->connection); } // do something during the loop // we mark the message for deletion here via this hook do_action('bp_rbe_imap_loop', $this->connection, $i); // unset some variables at the end of the loop unset($content, $headers, $data, $parser); } // do something after the loop do_action('bp_rbe_imap_after_loop', $this->connection); } // stop the loop if necessary if (bp_rbe_should_stop()) { if ($this->close()) { bp_rbe_log('--- Manual termination of connection confirmed! Kaching! ---'); } else { bp_rbe_log('--- Error - invalid connection during manual termination ---'); } remove_action('shutdown', 'bp_rbe_spawn_inbox_check'); exit; } // Give IMAP server a break sleep(10); // If the IMAP connection is down, reconnect if (!imap_ping($this->connection)) { bp_rbe_log('-- IMAP connection is down, attempting to reconnect... --'); if (bp_rbe_is_connecting(array('clearcache' => true))) { bp_rbe_log('--- RBE is already attempting to connect - stopping connection attempt ---'); continue; } // add lock marker before connecting bp_rbe_add_imap_lock(); // attempt to reconnect $reopen = BP_Reply_By_Email_Connect::init(array('reconnect' => true), $this->connection); if ($reopen) { bp_rbe_log('-- Reconnection successful! --'); } else { bp_rbe_log('-- Reconnection failed! :( --'); bp_rbe_log('Cannot connect: ' . imap_last_error()); // cleanup RBE after failure bp_rbe_cleanup(); remove_action('shutdown', 'bp_rbe_spawn_inbox_check'); exit; } } // Unset some variables to clear some memory unset($message_count); } if ($this->close()) { bp_rbe_log('--- Closing current connection automatically ---'); } else { bp_rbe_log('--- Invalid connection during close time ---'); } // autoconnect is off if (1 !== (int) bp_rbe_get_setting('keepaliveauto', array('refetch' => true))) { remove_action('shutdown', 'bp_rbe_spawn_inbox_check'); // sleep a bit before autoconnecting again } else { sleep(5); } exit; }