3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
14 * APIv3 functions for registering/processing mailing events.
16 * @package CiviCRM_APIv3
20 * Handle a create event.
22 * @param array $params
26 * @throws \API_Exception
27 * @throws \Civi\API\Exception\UnauthorizedException
29 function civicrm_api3_mailing_create($params) {
30 if (isset($params['template_options']) && is_array($params['template_options'])) {
31 $params['template_options'] = ($params['template_options'] === []) ?
'{}' : json_encode($params['template_options']);
33 $safeParams = $params;
34 $timestampCheck = TRUE;
35 if (!empty($params['id']) && !empty($params['modified_date'])) {
36 $timestampCheck = _civicrm_api3_compare_timestamps($safeParams['modified_date'], $safeParams['id'], 'Mailing');
37 unset($safeParams['modified_date']);
39 if (!$timestampCheck) {
40 throw new API_Exception("Mailing has not been saved, Content maybe out of date, please refresh the page and try again");
43 // FlexMailer is a refactoring of CiviMail which provides new hooks/APIs/docs. If the sysadmin has opted to enable it, then use that instead of CiviMail.
44 $safeParams['_evil_bao_validator_'] = \CRM_Utils_Constant
::value('CIVICRM_FLEXMAILER_HACK_SENDABLE', 'CRM_Mailing_BAO_Mailing::checkSendable');
45 $result = _civicrm_api3_basic_create(_civicrm_api3_get_BAO(__FUNCTION__
), $safeParams, 'Mailing');
46 return _civicrm_api3_mailing_get_formatResult($result);
50 * Get tokens for one or more entity type
52 * Output will be formatted either as a flat list,
53 * or pass sequential=1 to retrieve as a hierarchy formatted for select2.
55 * @param array $params
56 * Should contain an array of entities to retrieve tokens for.
59 * @throws \API_Exception
61 function civicrm_api3_mailing_gettokens($params) {
63 foreach ((array) $params['entity'] as $ent) {
64 $func = lcfirst($ent) . 'Tokens';
65 if (!method_exists('CRM_Core_SelectValues', $func)) {
66 throw new API_Exception('Unknown token entity: ' . $ent);
68 $tokens = array_merge(CRM_Core_SelectValues
::$func(), $tokens);
70 if (!empty($params['sequential'])) {
71 $tokens = CRM_Utils_Token
::formatTokensForDisplay($tokens);
73 return civicrm_api3_create_success($tokens, $params, 'Mailing', 'gettokens');
77 * Adjust Metadata for Create action.
79 * The metadata is used for setting defaults, documentation & validation.
81 * @param array $params
82 * Array of parameters determined by getfields.
84 function _civicrm_api3_mailing_gettokens_spec(&$params) {
86 'api.default' => ['contact'],
92 // Fetch a list of token functions and format to look like entity names
93 foreach (get_class_methods('CRM_Core_SelectValues') as $func) {
94 if (strpos($func, 'Tokens')) {
95 $ent = ucfirst(str_replace('Tokens', '', $func));
96 $params['entity']['options'][$ent] = $ent;
102 * Adjust Metadata for Create action.
104 * The metadata is used for setting defaults, documentation & validation.
106 * @param array $params
107 * Array of parameters determined by getfields.
109 function _civicrm_api3_mailing_create_spec(&$params) {
110 $params['created_id']['api.default'] = 'user_contact_id';
112 $params['override_verp']['api.default'] = !CRM_Core_BAO_Setting
::getItem(CRM_Core_BAO_Setting
::MAILING_PREFERENCES_NAME
, 'track_civimail_replies');
113 $params['visibility']['api.default'] = 'Public Pages';
114 $params['dedupe_email']['api.default'] = CRM_Core_BAO_Setting
::getItem(CRM_Core_BAO_Setting
::MAILING_PREFERENCES_NAME
, 'dedupe_email_default');
116 $params['forward_replies']['api.default'] = FALSE;
117 $params['auto_responder']['api.default'] = FALSE;
118 $params['open_tracking']['api.default'] = Civi
::settings()->get('open_tracking_default');
119 $params['url_tracking']['api.default'] = Civi
::settings()->get('url_tracking_default');
121 $params['header_id']['api.default'] = CRM_Mailing_PseudoConstant
::defaultComponent('Header', '');
122 $params['footer_id']['api.default'] = CRM_Mailing_PseudoConstant
::defaultComponent('Footer', '');
123 $params['optout_id']['api.default'] = CRM_Mailing_PseudoConstant
::defaultComponent('OptOut', '');
124 $params['reply_id']['api.default'] = CRM_Mailing_PseudoConstant
::defaultComponent('Reply', '');
125 $params['resubscribe_id']['api.default'] = CRM_Mailing_PseudoConstant
::defaultComponent('Resubscribe', '');
126 $params['unsubscribe_id']['api.default'] = CRM_Mailing_PseudoConstant
::defaultComponent('Unsubscribe', '');
127 $params['mailing_type']['api.default'] = 'standalone';
128 $defaultAddress = CRM_Core_BAO_Domain
::getNameAndEmail(TRUE, TRUE);
129 foreach ($defaultAddress as $value) {
130 if (preg_match('/"(.*)" <(.*)>/', $value, $match)) {
131 $params['from_email']['api.default'] = $match[2];
132 $params['from_name']['api.default'] = $match[1];
138 * Adjust metadata for clone spec action.
142 function _civicrm_api3_mailing_clone_spec(&$spec) {
143 $mailingFields = CRM_Mailing_DAO_Mailing
::fields();
144 $spec['id'] = $mailingFields['id'];
145 $spec['id']['api.required'] = 1;
151 * @param array $params
154 * @throws \CiviCRM_API3_Exception
156 function civicrm_api3_mailing_clone($params) {
166 'approval_status_id',
173 $get = civicrm_api3('Mailing', 'getsingle', ['id' => $params['id']]);
176 $newParams['debug'] = $params['debug'] ??
NULL;
177 $newParams['groups']['include'] = [];
178 $newParams['groups']['exclude'] = [];
179 $newParams['mailings']['include'] = [];
180 $newParams['mailings']['exclude'] = [];
181 foreach ($get as $field => $value) {
182 if (!in_array($field, $BLACKLIST)) {
183 $newParams[$field] = $value;
187 $dao = new CRM_Mailing_DAO_MailingGroup();
188 $dao->mailing_id
= $params['id'];
190 while ($dao->fetch()) {
191 // CRM-11431; account for multi-lingual
192 $entity = (substr($dao->entity_table
, 0, 15) == 'civicrm_mailing') ?
'mailings' : 'groups';
193 $newParams[$entity][strtolower($dao->group_type
)][] = $dao->entity_id
;
196 return civicrm_api3('Mailing', 'create', $newParams);
200 * Handle a delete event.
202 * @param array $params
207 function civicrm_api3_mailing_delete($params) {
208 return _civicrm_api3_basic_delete(_civicrm_api3_get_BAO(__FUNCTION__
), $params);
212 * Handle a get event.
214 * @param array $params
218 function civicrm_api3_mailing_get($params) {
219 $result = _civicrm_api3_basic_get(_civicrm_api3_get_BAO(__FUNCTION__
), $params, TRUE, 'Mailing');
220 return _civicrm_api3_mailing_get_formatResult($result);
226 * @param array $result
229 * @throws \CRM_Core_Exception
231 function _civicrm_api3_mailing_get_formatResult($result) {
232 if (isset($result['values']) && is_array($result['values'])) {
233 foreach ($result['values'] as $key => $caseType) {
234 if (isset($result['values'][$key]['template_options']) && is_string($result['values'][$key]['template_options'])) {
235 $result['values'][$key]['template_options'] = json_decode($result['values'][$key]['template_options'], TRUE);
243 * Adjust metadata for mailing submit api function.
247 function _civicrm_api3_mailing_submit_spec(&$spec) {
248 $mailingFields = CRM_Mailing_DAO_Mailing
::fields();
249 $spec['id'] = $mailingFields['id'];
250 $spec['scheduled_date'] = $mailingFields['scheduled_date'];
251 $spec['approval_date'] = $mailingFields['approval_date'];
252 $spec['approval_status_id'] = $mailingFields['approval_status_id'];
253 $spec['approval_note'] = $mailingFields['approval_note'];
254 // _skip_evil_bao_auto_recipients_: bool
260 * @param array $params
263 * @throws API_Exception
265 function civicrm_api3_mailing_submit($params) {
266 civicrm_api3_verify_mandatory($params, 'CRM_Mailing_DAO_Mailing', ['id']);
268 if (!isset($params['scheduled_date']) && !isset($updateParams['approval_date'])) {
269 throw new API_Exception("Missing parameter scheduled_date and/or approval_date");
271 if (!is_numeric(CRM_Core_Session
::getLoggedInContactID())) {
272 throw new API_Exception("Failed to determine current user");
276 $updateParams['id'] = $params['id'];
278 // Note: we'll pass along scheduling/approval fields, but they may get ignored
279 // if we don't have permission.
280 if (isset($params['scheduled_date'])) {
281 $updateParams['scheduled_date'] = $params['scheduled_date'];
282 $updateParams['scheduled_id'] = CRM_Core_Session
::getLoggedInContactID();
284 if (isset($params['approval_date'])) {
285 $updateParams['approval_date'] = $params['approval_date'];
286 $updateParams['approver_id'] = CRM_Core_Session
::getLoggedInContactID();
287 $updateParams['approval_status_id'] = CRM_Utils_Array
::value('approval_status_id', $updateParams, CRM_Core_OptionGroup
::getDefaultValue('mail_approval_status'));
289 if (isset($params['approval_note'])) {
290 $updateParams['approval_note'] = $params['approval_note'];
292 if (isset($params['_skip_evil_bao_auto_recipients_'])) {
293 $updateParams['_skip_evil_bao_auto_recipients_'] = $params['_skip_evil_bao_auto_recipients_'];
296 $updateParams['options']['reload'] = 1;
297 return civicrm_api3('Mailing', 'create', $updateParams);
301 * Process a bounce event by passing through to the BAOs.
303 * @param array $params
305 * @throws API_Exception
308 function civicrm_api3_mailing_event_bounce($params) {
309 $body = $params['body'];
310 unset($params['body']);
312 $params +
= CRM_Mailing_BAO_BouncePattern
::match($body);
314 if (CRM_Mailing_Event_BAO_Bounce
::create($params)) {
315 return civicrm_api3_create_success($params);
318 throw new API_Exception(ts('Queue event could not be found'), 'no_queue_event');
323 * Adjust Metadata for bounce_spec action.
325 * The metadata is used for setting defaults, documentation & validation.
327 * @param array $params
328 * Array of parameters determined by getfields.
330 function _civicrm_api3_mailing_event_bounce_spec(&$params) {
331 $params['job_id']['api.required'] = 1;
332 $params['job_id']['title'] = 'Job ID';
333 $params['event_queue_id']['api.required'] = 1;
334 $params['event_queue_id']['title'] = 'Event Queue ID';
335 $params['hash']['api.required'] = 1;
336 $params['hash']['title'] = 'Hash';
337 $params['body']['api.required'] = 1;
338 $params['body']['title'] = 'Body';
342 * Handle a confirm event.
346 * @param array $params
350 function civicrm_api3_mailing_event_confirm($params) {
351 return civicrm_api('MailingEventConfirm', 'create', $params);
355 * Declare deprecated functions.
357 * @deprecated api notice
359 * Array of deprecated actions
361 function _civicrm_api3_mailing_deprecation() {
362 return ['event_confirm' => 'Mailing api "event_confirm" action is deprecated. Use the mailing_event_confirm api instead.'];
366 * Handle a reply event.
368 * @param array $params
372 function civicrm_api3_mailing_event_reply($params) {
373 $job = $params['job_id'];
374 $queue = $params['event_queue_id'];
375 $hash = $params['hash'];
376 $replyto = $params['replyTo'];
377 $bodyTxt = $params['bodyTxt'] ??
NULL;
378 $bodyHTML = $params['bodyHTML'] ??
NULL;
379 $fullEmail = $params['fullEmail'] ??
NULL;
381 $mailing = CRM_Mailing_Event_BAO_Reply
::reply($job, $queue, $hash, $replyto);
383 if (empty($mailing)) {
384 return civicrm_api3_create_error('Queue event could not be found');
387 CRM_Mailing_Event_BAO_Reply
::send($queue, $mailing, $bodyTxt, $replyto, $bodyHTML, $fullEmail);
389 return civicrm_api3_create_success($params);
393 * Adjust Metadata for event_reply action.
395 * The metadata is used for setting defaults, documentation & validation.
397 * @param array $params
398 * Array of parameters determined by getfields.
400 function _civicrm_api3_mailing_event_reply_spec(&$params) {
401 $params['job_id']['api.required'] = 1;
402 $params['job_id']['title'] = 'Job ID';
403 $params['event_queue_id']['api.required'] = 1;
404 $params['event_queue_id']['title'] = 'Event Queue ID';
405 $params['hash']['api.required'] = 1;
406 $params['hash']['title'] = 'Hash';
407 $params['replyTo']['api.required'] = 0;
408 //doesn't really explain adequately
409 $params['replyTo']['title'] = 'Reply To';
413 * Handle a forward event.
415 * @param array $params
419 function civicrm_api3_mailing_event_forward($params) {
420 $job = $params['job_id'];
421 $queue = $params['event_queue_id'];
422 $hash = $params['hash'];
423 $email = $params['email'];
424 $fromEmail = $params['fromEmail'] ??
NULL;
425 $params = $params['params'] ??
NULL;
427 $forward = CRM_Mailing_Event_BAO_Forward
::forward($job, $queue, $hash, $email, $fromEmail, $params);
430 return civicrm_api3_create_success($params);
433 return civicrm_api3_create_error('Queue event could not be found');
437 * Adjust Metadata for event_forward action.
439 * The metadata is used for setting defaults, documentation & validation.
441 * @param array $params
442 * Array of parameters determined by getfields.
444 function _civicrm_api3_mailing_event_forward_spec(&$params) {
445 $params['job_id']['api.required'] = 1;
446 $params['job_id']['title'] = 'Job ID';
447 $params['event_queue_id']['api.required'] = 1;
448 $params['event_queue_id']['title'] = 'Event Queue ID';
449 $params['hash']['api.required'] = 1;
450 $params['hash']['title'] = 'Hash';
451 $params['email']['api.required'] = 1;
452 $params['email']['title'] = 'Forwarded to Email';
456 * Handle a click event.
458 * @param array $params
462 function civicrm_api3_mailing_event_click($params) {
463 civicrm_api3_verify_mandatory($params,
464 'CRM_Mailing_Event_DAO_TrackableURLOpen',
465 ['event_queue_id', 'url_id'],
469 $url_id = $params['url_id'];
470 $queue = $params['event_queue_id'];
472 $url = CRM_Mailing_Event_BAO_TrackableURLOpen
::track($queue, $url_id);
475 $values['url'] = $url;
476 $values['is_error'] = 0;
478 return civicrm_api3_create_success($values);
482 * Handle an open event.
484 * @param array $params
488 function civicrm_api3_mailing_event_open($params) {
490 civicrm_api3_verify_mandatory($params,
491 'CRM_Mailing_Event_DAO_Opened',
496 $queue = $params['event_queue_id'];
497 $success = CRM_Mailing_Event_BAO_Opened
::open($queue);
500 return civicrm_api3_create_error('mailing open event failed');
503 return civicrm_api3_create_success($params);
509 * @param array $params
510 * Array per getfields metadata.
513 * @throws \API_Exception
515 function civicrm_api3_mailing_preview($params) {
517 if (!empty($params['from_email'])) {
518 $fromEmail = $params['from_email'];
521 $mailing = new CRM_Mailing_BAO_Mailing();
522 $mailingID = $params['id'] ??
NULL;
524 $mailing->id
= $mailingID;
525 $mailing->find(TRUE);
528 $mailing->copyValues($params);
531 $session = CRM_Core_Session
::singleton();
533 CRM_Mailing_BAO_Mailing
::tokenReplace($mailing);
535 // get and format attachments
536 $attachments = CRM_Core_BAO_File
::getEntityFile('civicrm_mailing', $mailing->id
);
538 $returnProperties = $mailing->getReturnProperties();
539 $contactID = $params['contact_id'] ??
NULL;
541 // If we still don't have a userID in a session because we are annon then set contactID to be 0
542 $contactID = empty($session->get('userID')) ?
0 : $session->get('userID');
544 $mailingParams = ['contact_id' => $contactID];
547 $details = CRM_Utils_Token
::getAnonymousTokenDetails($mailingParams, $returnProperties, TRUE, TRUE, NULL, $mailing->getFlattenedTokens());
548 $details = $details[0][0] ??
NULL;
551 [$details] = CRM_Utils_Token
::getTokenDetails($mailingParams, $returnProperties, TRUE, TRUE, NULL, $mailing->getFlattenedTokens());
552 $details = $details[$contactID];
555 $mime = $mailing->compose(NULL, NULL, NULL, $contactID, $fromEmail, $fromEmail,
556 TRUE, $details, $attachments
559 return civicrm_api3_create_success([
561 'contact_id' => $contactID,
562 'subject' => CRM_Utils_Array
::value('Subject', $mime->headers(), ''),
563 'body_html' => $mime->getHTMLBody(),
564 'body_text' => $mime->getTXTBody(),
569 * Adjust metadata for send test function.
573 function _civicrm_api3_mailing_send_test_spec(&$spec) {
574 $spec['test_group']['title'] = 'Test Group ID';
575 $spec['test_email']['title'] = 'Test Email Address';
576 $spec['mailing_id']['api.required'] = TRUE;
577 $spec['mailing_id']['title'] = ts('Mailing Id');
583 * @param array $params
586 * @throws \API_Exception
587 * @throws \CiviCRM_API3_Exception
589 function civicrm_api3_mailing_send_test($params) {
590 if (!array_key_exists('test_group', $params) && !array_key_exists('test_email', $params)) {
591 throw new API_Exception("Mandatory key(s) missing from params array: test_group and/or test_email field are required");
593 civicrm_api3_verify_mandatory($params,
594 'CRM_Mailing_DAO_MailingJob',
599 $testEmailParams = _civicrm_api3_generic_replace_base_params($params);
600 if (isset($testEmailParams['id'])) {
601 unset($testEmailParams['id']);
604 $testEmailParams['is_test'] = 1;
605 $testEmailParams['status'] = 'Scheduled';
606 $testEmailParams['scheduled_date'] = CRM_Utils_Date
::processDate(date('Y-m-d'), date('H:i:s'));
607 $testEmailParams['is_calling_function_updated_to_reflect_deprecation'] = TRUE;
608 $job = civicrm_api3('MailingJob', 'create', $testEmailParams);
609 CRM_Mailing_BAO_Mailing
::getRecipients($testEmailParams['mailing_id']);
610 $testEmailParams['job_id'] = $job['id'];
611 $testEmailParams['emails'] = array_key_exists('test_email', $testEmailParams) ?
explode(',', strtolower($testEmailParams['test_email'])) : NULL;
612 if (!empty($params['test_email'])) {
613 $query = CRM_Utils_SQL_Select
::from('civicrm_email e')
614 ->select(['e.id', 'e.contact_id', 'e.email'])
615 ->join('c', 'INNER JOIN civicrm_contact c ON e.contact_id = c.id')
616 ->where('e.email IN (@emails)', ['@emails' => $testEmailParams['emails']])
617 ->where('e.on_hold = 0')
618 ->where('c.is_opt_out = 0')
619 ->where('c.do_not_email = 0')
620 ->where('c.is_deceased = 0')
621 ->where('c.is_deleted = 0')
623 ->orderBy(['e.is_bulkmail DESC', 'e.is_primary DESC'])
625 $dao = CRM_Core_DAO
::executeQuery($query);
627 // fetch contact_id and email id for all existing emails
628 while ($dao->fetch()) {
629 $emailDetail[strtolower($dao->email
)] = [
630 'contact_id' => $dao->contact_id
,
631 'email_id' => $dao->id
,
634 foreach ($testEmailParams['emails'] as $key => $email) {
635 $email = trim($email);
636 $contactId = $emailId = NULL;
637 if (array_key_exists($email, $emailDetail)) {
638 $emailId = $emailDetail[$email]['email_id'];
639 $contactId = $emailDetail[$email]['contact_id'];
641 if (!$contactId && CRM_Core_Permission
::check('add contacts')) {
642 //create new contact.
643 $contact = civicrm_api3('Contact', 'create',
645 'contact_type' => 'Individual',
647 'api.Email.get' => ['return' => 'id'],
650 $contactId = $contact['id'];
651 $emailId = $contact['values'][$contactId]['api.Email.get']['id'];
653 if ($emailId && $contactId) {
654 civicrm_api3('MailingEventQueue', 'create',
656 'job_id' => $job['id'],
657 'email_id' => $emailId,
658 'contact_id' => $contactId,
667 while (!$isComplete) {
668 // Q: In CRM_Mailing_BAO_Mailing::processQueue(), the three runJobs*()
669 // functions are all called. Why does Mailing.send_test only call one?
670 // CRM_Mailing_BAO_MailingJob::runJobs_pre($mailerJobSize, NULL);
671 $isComplete = CRM_Mailing_BAO_MailingJob
::runJobs($testEmailParams);
672 // CRM_Mailing_BAO_MailingJob::runJobs_post(NULL);
675 //return delivered mail info
676 $mailDelivered = CRM_Mailing_Event_BAO_Delivered
::getRows($params['mailing_id'], $job['id'], TRUE, NULL, NULL, NULL, TRUE);
678 return civicrm_api3_create_success($mailDelivered);
682 * Adjust Metadata for send_mail action.
684 * The metadata is used for setting defaults, documentation & validation.
686 * @param array $params
687 * Array of parameters determined by getfields.
689 function _civicrm_api3_mailing_stats_spec(&$params) {
690 $params['date']['api.default'] = 'now';
691 $params['date']['title'] = 'Date';
692 $params['is_distinct']['api.default'] = FALSE;
693 $params['is_distinct']['title'] = 'Is Distinct';
697 * Function which needs to be explained.
699 * @param array $params
702 * @throws \API_Exception
704 function civicrm_api3_mailing_stats($params) {
705 civicrm_api3_verify_mandatory($params,
706 'CRM_Mailing_DAO_MailingJob',
711 if ($params['date'] == 'now') {
712 $params['date'] = date('YmdHis');
715 $params['date'] = CRM_Utils_Date
::processDate($params['date'] . ' ' . $params['date_time']);
718 $stats[$params['mailing_id']] = [];
719 if (empty($params['job_id'])) {
720 $params['job_id'] = NULL;
722 foreach (['Delivered', 'Bounces', 'Unsubscribers', 'Unique Clicks', 'Opened'] as $detail) {
725 $stats[$params['mailing_id']] +
= [
726 $detail => CRM_Mailing_Event_BAO_Delivered
::getTotalCount($params['mailing_id'], $params['job_id'], (bool) $params['is_distinct'], $params['date']),
731 $stats[$params['mailing_id']] +
= [
732 $detail => CRM_Mailing_Event_BAO_Bounce
::getTotalCount($params['mailing_id'], $params['job_id'], (bool) $params['is_distinct'], $params['date']),
736 case 'Unsubscribers':
737 $stats[$params['mailing_id']] +
= [
738 $detail => CRM_Mailing_Event_BAO_Unsubscribe
::getTotalCount($params['mailing_id'], $params['job_id'], (bool) $params['is_distinct'], NULL, $params['date']),
742 case 'Unique Clicks':
743 $stats[$params['mailing_id']] +
= [
744 $detail => CRM_Mailing_Event_BAO_TrackableURLOpen
::getTotalCount($params['mailing_id'], $params['job_id'], (bool) $params['is_distinct'], NULL, $params['date']),
749 $stats[$params['mailing_id']] +
= [
750 $detail => CRM_Mailing_Event_BAO_Opened
::getTotalCount($params['mailing_id'], $params['job_id'], (bool) $params['is_distinct'], $params['date']),
755 $stats[$params['mailing_id']]['delivered_rate'] = $stats[$params['mailing_id']]['opened_rate'] = $stats[$params['mailing_id']]['clickthrough_rate'] = '0.00%';
756 if (!empty(CRM_Mailing_Event_BAO_Queue
::getTotalCount($params['mailing_id'], $params['job_id']))) {
757 $stats[$params['mailing_id']]['delivered_rate'] = round((100.0 * $stats[$params['mailing_id']]['Delivered']) / CRM_Mailing_Event_BAO_Queue
::getTotalCount($params['mailing_id'], $params['job_id']), 2) . '%';
759 if (!empty($stats[$params['mailing_id']]['Delivered'])) {
760 $stats[$params['mailing_id']]['opened_rate'] = round($stats[$params['mailing_id']]['Opened'] / $stats[$params['mailing_id']]['Delivered'] * 100.0, 2) . '%';
761 $stats[$params['mailing_id']]['clickthrough_rate'] = round($stats[$params['mailing_id']]['Unique Clicks'] / $stats[$params['mailing_id']]['Delivered'] * 100.0, 2) . '%';
763 return civicrm_api3_create_success($stats);
766 function _civicrm_api3_mailing_update_email_resetdate_spec(&$spec) {
767 $spec['minDays']['title'] = 'Number of days to wait without a bounce to assume successful delivery (default 3)';
768 $spec['minDays']['type'] = CRM_Utils_Type
::T_INT
;
769 $spec['minDays']['api.default'] = 3;
770 $spec['minDays']['api.required'] = 1;
772 $spec['maxDays']['title'] = 'Analyze mailings since this many days ago (default 7)';
773 $spec['maxDays']['type'] = CRM_Utils_Type
::T_INT
;
774 $spec['maxDays']['api.default'] = 7;
775 $spec['maxDays']['api.required'] = 1;
779 * Fix the reset dates on the email record based on when a mail was last delivered.
781 * We only consider mailings that were completed and finished in the last 3 to 7 days
782 * Both the min and max days can be set via the params
784 * @param array $params
788 function civicrm_api3_mailing_update_email_resetdate($params) {
789 CRM_Mailing_Event_BAO_Delivered
::updateEmailResetDate((int) $params['minDays'], (int) $params['maxDays']);
790 return civicrm_api3_create_success();