/** * Implementation of hook_civicrm_pageRun * * Handler for pageRun hook. */ function mailjet_civicrm_pageRun(&$page) { if (get_class($page) == 'CRM_Mailing_Page_Report') { $mailingId = $page->_mailing_id; $mailingJobs = civicrm_api3('MailingJob', 'get', $params = array('mailing_id' => $mailingId)); $stats = array('BlockedCount' => 0, 'BouncedCount' => 0, 'ClickedCount' => 0, 'DeliveredCount' => 0, 'OpenedCount' => 0, 'ProcessedCount' => 0, 'QueuedCount' => 0, 'SpamComplaintCount' => 0, 'UnsubscribedCount' => 0); foreach ($mailingJobs['values'] as $key => $job) { if ($job['job_type'] == 'child') { $jobId = $key; require_once 'packages/mailjet-0.3/php-mailjet-v3-simple.class.php'; // Create a new Mailjet Object $mj = new Mailjet(MAILJET_API_KEY, MAILJET_SECRET_KEY); $mj->debug = 0; $mailJetParams = array('method' => 'VIEW', 'unique' => CRM_Mailjet_BAO_Event::getMailjetCustomCampaignId($jobId)); $response = $mj->campaign($mailJetParams); $page->assign('mailjet_params', $mailJetParams); if (!empty($response)) { if ($response->Count == 1) { $campaign = $response->Data[0]; $mailJetParams = array('method' => 'VIEW', 'unique' => $campaign->ID); $response = $mj->campaignstatistics($mailJetParams); if ($response->Count == 1) { $stats = sumUpStats($stats, get_object_vars($response->Data[0])); } } } } } $page->assign('mailjet_stats', $stats); CRM_Core_Region::instance('page-header')->add(array('template' => 'CRM/Mailjet/Page/Report.tpl')); } }
function processMessage($msg) { //Decode Trigger Informations $trigger = json_decode($msg, true); //No Informations sent with the Event if (!is_array($trigger) || !isset($trigger['event'])) { CRM_Core_Error::debug_var("ENDPOINT EVENT", "Invalid JSON or no event", true, true); return 'HTTP/1.1 422 Not ok'; } $event = trim($trigger['event']); $email = trim($trigger['email']); $time = date('YmdHis', $trigger['time']); $mailingId = CRM_Utils_Array::value('customcampaign', $trigger); //CiviCRM mailling ID //PERFORANCE IMPACT, xav CRM_Core_Error::debug_var("MAILJET TRIGGER", $trigger, true, true); if (substr($mailingId, 0, 5) === "TRANS" || substr($mailingId, 0, 15) === "=?utf-8?Q?TRANS") { //PERFORANCE IMPACT, xav CRM_Core_Error::debug_var("TRANS EMAIL", array($mailingId, $event, $email), true, true); $allowedEvents = array('bounce', 'blocked', 'spam', 'unsub'); if (!in_array($event, $allowedEvents)) { return 'HTTP/1.1 200 Ok'; } $emailResult = civicrm_api3('Email', 'get', array('email' => $email, 'sequential' => 1)); if (isset($emailResult['values']) && !empty($emailResult['values'])) { //we always get the first result $emailId = $emailResult['values'][0]['id']; $contactId = $emailResult['values'][0]['contact_id']; if ($event == 'bounce' && $trigger['hard_bounce']) { $params = array('sequential' => 1, 'id' => $emailId, 'email' => $email, 'on_hold' => 2, 'hold_date' => date('YmdHis')); civicrm_api3('Email', 'create', $params); } $params = array('sequential' => 1, 'activity_type_id' => 58, 'activity_date_time' => $time, 'status_id' => 'Completed', 'subject' => $event, 'details' => 'Added by mailjet extension, error: ' . CRM_Utils_Array::value('error_related_to', $trigger) . ', ' . CRM_Utils_Array::value('error', $trigger) . '. blocked=' . (int) CRM_Utils_Array::value('blocked', $trigger) . '. hard_bounce=' . (int) CRM_Utils_Array::value('hard_bounce', $trigger), 'source_contact_id' => $contactId); civicrm_api3('Activity', 'create', $params); } if ($event == 'unsub') { $params = array('sequential' => 1, 'id' => $emailId, 'email' => $email, 'on_hold' => 2, 'hold_date' => date('YmdHis')); civicrm_api3('Email', 'create', $params); $params = array('sequential' => 1, 'id' => $contactId, 'is_opt_out' => 1); civicrm_api3('Contact', 'create', $params); } return 'HTTP/1.1 200 Ok'; } if ($mailingId && $mailingId[0] != '0') { //we only process if mailing_id exist - marketing email /* https://www.mailjet.com/docs/event_tracking for more informations. */ switch ($event) { //For unsupported events, we just store them raw case 'open': case 'click': case 'unsub': case 'typofix': CRM_Mailjet_BAO_Event::createFromPostData($trigger); return 'HTTP/1.1 200 Ok'; //We replace the civi delivery time with the mailjet one //but keep the civi one for comparison //We replace the civi delivery time with the mailjet one //but keep the civi one for comparison case 'sent': $emailResult = civicrm_api3('Email', 'get', array('email' => $email, 'sequential' => 1)); if (isset($emailResult['values']) && !empty($emailResult['values'])) { CRM_Mailjet_Page_EndPoint::updateDelivery($trigger, $emailResult); return 'HTTP/1.1 200 Ok'; } else { //This shouldn't happen, let's log the event CRM_Mailjet_BAO_Event::createFromPostData($trigger); CRM_Core_Error::debug_var("MAILJET TRIGGER", "Unknown address {$email}", true, true); return 'HTTP/1.1 422 unknown email address'; } //we treat bounce, span and blocked as bounce mailing in CiviCRM //we treat bounce, span and blocked as bounce mailing in CiviCRM case 'bounce': case 'spam': case 'blocked': $emailResult = civicrm_api3('Email', 'get', array('email' => $email, 'sequential' => 1)); if (isset($emailResult['values']) && !empty($emailResult['values'])) { $params = CRM_Mailjet_Page_EndPoint::prepareBounceParams($trigger, $emailResult); CRM_Mailjet_BAO_Event::recordBounce($params); return 'HTTP/1.1 200 Ok'; } else { //This shouldn't happen, let's log the event CRM_Mailjet_BAO_Event::createFromPostData($trigger); CRM_Core_Error::debug_var("MAILJET TRIGGER", "Unknown address {$email}", true, true); return 'HTTP/1.1 422 unknown email address'; } # No handler # No handler default: CRM_Core_Error::debug_var("MAILJET TRIGGER", "No handler for {$event}", true, true); return 'HTTP/1.1 422 unknown event'; } } else { //assumed if there is not mailing_id, this should be a transaction email //TODO::process a transaction email } return 'HTTP/1.1 200 Ok'; }
/** * Process the mailjet bounce emails * * @return boolean always returns true (for the api). at a later stage we should * fix this to return true on success / false on failure etc */ static function processBounces($mailingId = NULL) { require_once 'packages/mailjet-0.1/php-mailjet.class-mailjet-0.1.php'; // Create a new Mailjet Object @php-mailjet.class-mailjet-0.1.php $mj = new Mailjet(MAILJET_API_KEY, MAILJET_SECRET_KEY); //G: TODO $mj->debug = 0; if ($mailingId) { $apiParams = array('mailing_id' => $mailingId); $campaignJobId = 0; $mailJobResult = civicrm_api3('MailingJob', 'get', $apiParams); foreach ($mailJobResult['values'] as $jobId => $currentJob) { if (isset($currentJob['job_type'])) { $jobType = $currentJob['job_type']; //if job is not test if ($jobType == 'child') { $campaignJobId = $jobId; } } } $mailjetParams = array('custom_campaign' => CRM_Mailjet_BAO_Event::getMailjetCustomCampaignId($campaignJobId)); //G: https://uk.mailjet.com/docs/api/message/list //List all your messages (both transactional and campaign) with numerous filters. $response = $mj->messageList($mailjetParams); if (!$response) { return TRUE; //always return true - we don't process bounces if there is no reponse. } $campaign = $response->result[0]; //G: https://uk.mailjet.com/docs/api/report/emailbounce //Lists emails declared as bounce. //Call $response = $mj->reportEmailBounce(array('campaign_id' => $campaign->id)); } else { $response = $mj->reportEmailBounce(); } //Result $bounces = $response->bounces; foreach ($bounces as $bounce) { $params = array('email' => $bounce->email, 'sequential' => 1); $emailResult = civicrm_api3('Email', 'get', $params); if (!empty($emailResult['values'])) { //we always get the first result //TODO: might related to bounce record issue $contactId = $emailResult['values'][0]['contact_id']; $emailId = $emailResult['values'][0]['id']; $emailAddress = $emailResult['values'][0]['email']; if (!$bounce->customcampaign) { //do not process bounce if we dont have custom campaign continue; } $campaingArray = explode("MJ", $bounce->customcampaign); //TODO: related to bounce record issue $jobId = $campaingArray[0]; $mailingJobResult = civicrm_api3('MailingJob', 'get', array('id' => $jobId)); $mailingResult = civicrm_api3('Mailing', 'get', array('id' => $mailingJobResult['values'][$jobId]['mailing_id'])); $currentMailingId = 0; foreach ($mailingResult['values'] as $mailingId => $mailing) { $currentMailingId = $mailingId; } /*$params = array( 'mailing_id' => $mailingId, ); $result = civicrm_api3('MailingJob', 'get', $params); $jobIds = array(); foreach ($result['values'] as $id => $value) { $jobIds[] = $id; } $jobIds = implode(",", $jobIds); $params = array( 1 => array( $contactId, 'Integer'), 2 => array( $emailId, 'Integer') );*/ $query = "SELECT eq.id\n FROM civicrm_mailing_event_bounce eb\n LEFT JOIN civicrm_mailing_event_queue eq ON eq.id = eb.event_queue_id\n WHERE 1\n AND eq.job_id = {$jobId}\n AND eq.email_id = {$emailId}\n AND eq.contact_id = {$contactId}"; $dao = CRM_Core_DAO::executeQuery($query); $isBounceRecord = FALSE; while ($dao->fetch()) { $isBounceRecord = TRUE; break; } //if bounce record doesn't exsit so we record it if (!$isBounceRecord) { $bounceArray = array('is_spam' => FALSE, 'mailing_id' => $currentMailingId, 'job_id' => $jobId, 'contact_id' => $contactId, 'email_id' => $emailId, 'email' => $emailAddress, 'blocked' => 0, 'hard_bounce' => $bounce->hard_bounce, 'date_ts' => $bounce->date_ts, 'error_related_to' => $bounce->error_related_to, 'error' => $bounce->error); CRM_Mailjet_BAO_Event::recordBounce($bounceArray); } } } // always returns true, i.e. never fails :) return TRUE; }