/** * Form rule to send out a test mailing. * * @param aray $testParams * @param array $files * Any files posted to the form. * @param array $self * An current this object. * * @return bool * true on successful SMTP handoff */ public static function testMail($testParams, $files, $self) { $error = NULL; $urlString = 'civicrm/mailing/send'; $urlParams = "_qf_Test_display=true&qfKey={$testParams['qfKey']}"; $ssID = $self->get('ssID'); if ($ssID && $self->_searchBasedMailing) { if ($self->_action == CRM_Core_Action::BASIC) { $fragment = 'search'; } elseif ($self->_action == CRM_Core_Action::PROFILE) { $fragment = 'search/builder'; } elseif ($self->_action == CRM_Core_Action::ADVANCED) { $fragment = 'search/advanced'; } else { $fragment = 'search/custom'; } $urlString = 'civicrm/contact/' . $fragment; } $emails = NULL; if (!empty($testParams['sendtest'])) { if (!($testParams['test_group'] || $testParams['test_email'])) { CRM_Core_Session::setStatus(ts('You did not provide an email address or select a group.'), ts('Test not sent.'), 'error'); $error = TRUE; } if ($testParams['test_email']) { $emailAdd = explode(',', $testParams['test_email']); foreach ($emailAdd as $key => $value) { $email = trim($value); $testParams['emails'][] = $email; $emails .= ($emails ? ',' : '') . "'" . CRM_Core_DAO::escapeString($email) . "'"; if (!CRM_Utils_Rule::email($email)) { CRM_Core_Session::setStatus(ts('Please enter a valid email address.'), ts('Test not sent.'), 'error'); $error = TRUE; } } } if ($error) { $url = CRM_Utils_System::url($urlString, $urlParams); CRM_Utils_System::redirect($url); return $error; } } if (!empty($testParams['_qf_Test_submit'])) { //when user perform mailing from search context //redirect it to search result CRM-3711. if ($ssID && $self->_searchBasedMailing) { $draftURL = CRM_Utils_System::url('civicrm/mailing/browse/unscheduled', 'scheduled=false&reset=1'); $status = ts("You can continue later by clicking the 'Continue' action to resume working on it.<br />From <a href='%1'>Draft and Unscheduled Mailings</a>.", array(1 => $draftURL)); //replace user context to search. $context = $self->get('context'); if (!CRM_Contact_Form_Search::isSearchContext($context)) { $context = 'search'; } $urlParams = "force=1&reset=1&ssID={$ssID}&context={$context}&qfKey={$testParams['qfKey']}"; $url = CRM_Utils_System::url($urlString, $urlParams); } else { $status = ts("Click the 'Continue' action to resume working on it."); $url = CRM_Utils_System::url('civicrm/mailing/browse/unscheduled', 'scheduled=false&reset=1'); } CRM_Core_Session::setStatus($status, ts('Mailing Saved'), 'success'); CRM_Utils_System::redirect($url); } if (CRM_Mailing_Info::workflowEnabled()) { if (!CRM_Core_Permission::check('schedule mailings') && CRM_Core_Permission::check('create mailings')) { $url = CRM_Utils_System::url('civicrm/mailing/browse/unscheduled', 'scheduled=false&reset=1'); CRM_Utils_System::redirect($url); } } if (!empty($testParams['_qf_Test_next']) && $self->get('count') <= 0) { return array('_qf_default' => ts("You can not schedule or send this mailing because there are currently no recipients selected. Click 'Previous' to return to the Select Recipients step, OR click 'Save & Continue Later'.")); } if (!empty($_POST['_qf_Import_refresh']) || !empty($testParams['_qf_Test_next']) || empty($testParams['sendtest'])) { $error = TRUE; return $error; } $job = new CRM_Mailing_BAO_MailingJob(); $job->mailing_id = $self->get('mailing_id'); $job->is_test = TRUE; $job->save(); $newEmails = NULL; $session = CRM_Core_Session::singleton(); if (!empty($testParams['emails'])) { $query = "\nSELECT e.id, e.contact_id, e.email\nFROM civicrm_email e\nINNER JOIN civicrm_contact c ON e.contact_id = c.id\nWHERE e.email IN ({$emails})\nAND e.on_hold = 0\nAND c.is_opt_out = 0\nAND c.do_not_email = 0\nAND c.is_deleted = 0\nAND c.is_deceased = 0\nGROUP BY e.id\nORDER BY e.is_bulkmail DESC, e.is_primary DESC\n"; $dao = CRM_Core_DAO::executeQuery($query); $emailDetail = array(); // fetch contact_id and email id for all existing emails while ($dao->fetch()) { $emailDetail[$dao->email] = array('contact_id' => $dao->contact_id, 'email_id' => $dao->id); } $dao->free(); foreach ($testParams['emails'] as $key => $email) { // Email addresses are forced to lower case when saved, so ensure // we have the same case when comparing. $email = trim(strtolower($email)); $contactId = $emailId = NULL; if (array_key_exists($email, $emailDetail)) { $emailId = $emailDetail[$email]['email_id']; $contactId = $emailDetail[$email]['contact_id']; } if (!$contactId) { //create new contact. $params = array('contact_type' => 'Individual', 'email' => array(1 => array('email' => $email, 'is_primary' => 1, 'location_type_id' => 1))); $contact = CRM_Contact_BAO_Contact::create($params); $emailId = $contact->email[0]->id; $contactId = $contact->id; $contact->free(); } $params = array('job_id' => $job->id, 'email_id' => $emailId, 'contact_id' => $contactId); CRM_Mailing_Event_BAO_Queue::create($params); } } $testParams['job_id'] = $job->id; $isComplete = FALSE; while (!$isComplete) { $isComplete = CRM_Mailing_BAO_MailingJob::runJobs($testParams); } if (!empty($testParams['sendtest'])) { $status = NULL; if (CRM_Mailing_Info::workflowEnabled()) { if (CRM_Core_Permission::check('schedule mailings') && CRM_Core_Permission::check('create mailings') || CRM_Core_Permission::check('access CiviMail')) { $status = ts("Click 'Next' when you are ready to Schedule or Send your live mailing (you will still have a chance to confirm or cancel sending this mailing on the next page)."); } } else { $status = ts("Click 'Next' when you are ready to Schedule or Send your live mailing (you will still have a chance to confirm or cancel sending this mailing on the next page)."); } if ($status) { CRM_Core_Session::setStatus($status, ts('Test message sent'), 'success'); } $url = CRM_Utils_System::url($urlString, $urlParams); CRM_Utils_System::redirect($url); } $error = TRUE; return $error; }
if (isset($options['h'])) { print "\nUsage: php civimail-spooler.php [-bh] [-c <config>] [-t <period>]\n"; print " -b Run this process continuously\n"; print " -c Path to CiviCRM civicrm.settings.php\n"; print " -h Print this help message\n"; print " -t In continuous mode, the period (in seconds) to wait between queue events\n\n"; exit; } if (isset($options['c'])) { $config_file = $options['c']; } eval(' require_once "$config_file"; require_once "CRM/Core/Config.php"; '); $config =& CRM_Core_Config::singleton(); /* Temporary permissioning hack for now */ CRM_Utils_System_Soap::swapUF(); if (isset($options['t']) && is_int($options['t']) && $options['t'] > 0) { $config->mailerPeriod = $options['t']; } if (isset($options['b'])) { while (TRUE) { /* TODO: put some syslog calls in here. Also, we may want to fork the * process into the background and provide init.d scripts */ CRM_Mailing_BAO_MailingJob::runJobs(); sleep($config->mailerPeriod); } } else { CRM_Mailing_BAO_MailingJob::runJobs(); }
/** * @param null $mode * * @return bool * @throws Exception */ public static function processQueue($mode = NULL) { $config = CRM_Core_Config::singleton(); if ($mode == NULL && CRM_Core_BAO_MailSettings::defaultDomain() == "EXAMPLE.ORG") { throw new CRM_Core_Exception(ts('The <a href="%1">default mailbox</a> has not been configured. You will find <a href="%2">more info in the online user and administrator guide</a>', array(1 => CRM_Utils_System::url('civicrm/admin/mailSettings', 'reset=1'), 2 => "http://book.civicrm.org/user/advanced-configuration/email-system-configuration/"))); } // check if we are enforcing number of parallel cron jobs // CRM-8460 $gotCronLock = FALSE; if (property_exists($config, 'mailerJobsMax') && $config->mailerJobsMax && $config->mailerJobsMax > 0) { $lockArray = range(1, $config->mailerJobsMax); shuffle($lockArray); // check if we are using global locks foreach ($lockArray as $lockID) { $cronLock = Civi\Core\Container::singleton()->get('lockManager')->acquire("worker.mailing.send.{$lockID}"); if ($cronLock->isAcquired()) { $gotCronLock = TRUE; break; } } // exit here since we have enuf cronjobs running if (!$gotCronLock) { CRM_Core_Error::debug_log_message('Returning early, since max number of cronjobs running'); return TRUE; } if (getenv('CIVICRM_CRON_HOLD')) { // In testing, we may need to simulate some slow activities. sleep(getenv('CIVICRM_CRON_HOLD')); } } // load bootstrap to call hooks // Split up the parent jobs into multiple child jobs $mailerJobSize = property_exists($config, 'mailerJobSize') ? $config->mailerJobSize : NULL; CRM_Mailing_BAO_MailingJob::runJobs_pre($mailerJobSize, $mode); CRM_Mailing_BAO_MailingJob::runJobs(NULL, $mode); CRM_Mailing_BAO_MailingJob::runJobs_post($mode); // lets release the global cron lock if we do have one if ($gotCronLock) { $cronLock->release(); } return TRUE; }
/** * Send test mailing. * * @param array $params * * @return array * @throws \API_Exception * @throws \CiviCRM_API3_Exception */ function civicrm_api3_mailing_send_test($params) { if (!array_key_exists('test_group', $params) && !array_key_exists('test_email', $params)) { throw new API_Exception("Mandatory key(s) missing from params array: test_group and/or test_email field are required"); } civicrm_api3_verify_mandatory($params, 'CRM_Mailing_DAO_MailingJob', array('mailing_id'), FALSE); $testEmailParams = _civicrm_api3_generic_replace_base_params($params); $testEmailParams['is_test'] = 1; $job = civicrm_api3('MailingJob', 'create', $testEmailParams); $testEmailParams['job_id'] = $job['id']; $testEmailParams['emails'] = explode(',', $testEmailParams['test_email']); if (!empty($params['test_email'])) { $query = CRM_Utils_SQL_Select::from('civicrm_email e')->select(array('e.id', 'e.contact_id', 'e.email'))->join('c', 'INNER JOIN civicrm_contact c ON e.contact_id = c.id')->where('e.email IN (@emails)', array('@emails' => $testEmailParams['emails']))->where('e.on_hold = 0')->where('c.is_opt_out = 0')->where('c.do_not_email = 0')->where('c.is_deceased = 0')->where('c.is_deleted = 0')->groupBy('e.id')->orderBy(array('e.is_bulkmail DESC', 'e.is_primary DESC'))->toSQL(); $dao = CRM_Core_DAO::executeQuery($query); $emailDetail = array(); // fetch contact_id and email id for all existing emails while ($dao->fetch()) { $emailDetail[$dao->email] = array('contact_id' => $dao->contact_id, 'email_id' => $dao->id); } $dao->free(); foreach ($testEmailParams['emails'] as $key => $email) { $email = trim($email); $contactId = $emailId = NULL; if (array_key_exists($email, $emailDetail)) { $emailId = $emailDetail[$email]['email_id']; $contactId = $emailDetail[$email]['contact_id']; } if (!$contactId) { //create new contact. $contact = civicrm_api3('Contact', 'create', array('contact_type' => 'Individual', 'email' => $email, 'api.Email.get' => array('return' => 'id'))); $contactId = $contact['id']; $emailId = $contact['values'][$contactId]['api.Email.get']['id']; } civicrm_api3('MailingEventQueue', 'create', array('job_id' => $job['id'], 'email_id' => $emailId, 'contact_id' => $contactId)); } } $isComplete = FALSE; $config = CRM_Core_Config::singleton(); $mailerJobSize = Civi::settings()->get('mailerJobSize'); while (!$isComplete) { // Q: In CRM_Mailing_BAO_Mailing::processQueue(), the three runJobs*() // functions are all called. Why does Mailing.send_test only call one? // CRM_Mailing_BAO_MailingJob::runJobs_pre($mailerJobSize, NULL); $isComplete = CRM_Mailing_BAO_MailingJob::runJobs($testEmailParams); // CRM_Mailing_BAO_MailingJob::runJobs_post(NULL); } //return delivered mail info $mailDelivered = CRM_Mailing_Event_BAO_Delivered::getRows($params['mailing_id'], $job['id'], TRUE, NULL, NULL, NULL, TRUE); return civicrm_api3_create_success($mailDelivered); }
/** * Run this page (figure out the action needed and perform it). */ public function run() { $this->preProcess(); $newArgs = func_get_args(); // since we want only first function argument $newArgs = $newArgs[0]; if (isset($_GET['runJobs']) || CRM_Utils_Array::value('2', $newArgs) == 'queue') { $mailerJobSize = Civi::settings()->get('mailerJobSize'); CRM_Mailing_BAO_MailingJob::runJobs_pre($mailerJobSize); CRM_Mailing_BAO_MailingJob::runJobs(); CRM_Mailing_BAO_MailingJob::runJobs_post(); } $this->_sortByCharacter = CRM_Utils_Request::retrieve('sortByCharacter', 'String', $this); // CRM-11920 all should set sortByCharacter to null, not empty string if (strtolower($this->_sortByCharacter) == 'all' || !empty($_POST)) { $this->_sortByCharacter = NULL; $this->set('sortByCharacter', NULL); } if (CRM_Utils_Array::value(3, $newArgs) == 'unscheduled') { $this->_unscheduled = TRUE; } $this->set('unscheduled', $this->_unscheduled); if (CRM_Utils_Array::value(3, $newArgs) == 'archived') { $this->_archived = TRUE; } $this->set('archived', $this->_archived); if (CRM_Utils_Array::value(3, $newArgs) == 'scheduled') { $this->_scheduled = TRUE; } $this->set('scheduled', $this->_scheduled); $this->_createdId = CRM_Utils_Request::retrieve('cid', 'Positive', $this, FALSE, 0); if ($this->_createdId) { $this->set('createdId', $this->_createdId); } if ($this->_sms) { $this->set('sms', $this->_sms); } $session = CRM_Core_Session::singleton(); $context = $session->readUserContext(); if ($this->_action & CRM_Core_Action::DISABLE) { if (CRM_Utils_Request::retrieve('confirmed', 'Boolean', $this)) { CRM_Mailing_BAO_MailingJob::cancel($this->_mailingId); CRM_Utils_System::redirect($context); } else { $controller = new CRM_Core_Controller_Simple('CRM_Mailing_Form_Browse', ts('Cancel Mailing'), $this->_action); $controller->setEmbedded(TRUE); $controller->run(); } } elseif ($this->_action & CRM_Core_Action::DELETE) { if (CRM_Utils_Request::retrieve('confirmed', 'Boolean', $this)) { // check for action permissions. if (!CRM_Core_Permission::checkActionPermission('CiviMail', $this->_action)) { CRM_Core_Error::fatal(ts('You do not have permission to access this page.')); } CRM_Mailing_BAO_Mailing::del($this->_mailingId); CRM_Utils_System::redirect($context); } else { $controller = new CRM_Core_Controller_Simple('CRM_Mailing_Form_Browse', ts('Delete Mailing'), $this->_action); $controller->setEmbedded(TRUE); $controller->run(); } } elseif ($this->_action & CRM_Core_Action::RENEW) { // archive this mailing, CRM-3752. if (CRM_Utils_Request::retrieve('confirmed', 'Boolean', $this)) { // set is_archived to 1 CRM_Core_DAO::setFieldValue('CRM_Mailing_DAO_Mailing', $this->_mailingId, 'is_archived', TRUE); CRM_Utils_System::redirect($context); } else { $controller = new CRM_Core_Controller_Simple('CRM_Mailing_Form_Browse', ts('Archive Mailing'), $this->_action); $controller->setEmbedded(TRUE); $controller->run(); } } $selector = new CRM_Mailing_Selector_Browse(); $selector->setParent($this); $controller = new CRM_Core_Selector_Controller($selector, $this->get(CRM_Utils_Pager::PAGE_ID), $this->get(CRM_Utils_Sort::SORT_ID) . $this->get(CRM_Utils_Sort::SORT_DIRECTION), CRM_Core_Action::VIEW, $this, CRM_Core_Selector_Controller::TEMPLATE); $controller->setEmbedded(TRUE); $controller->run(); // hack to display results as per search $rows = $controller->getRows($controller); $this->assign('rows', $rows); $urlParams = 'reset=1'; $urlString = 'civicrm/mailing/browse'; if ($this->get('sms')) { $urlParams .= '&sms=1'; } if (CRM_Utils_Array::value(3, $newArgs) == 'unscheduled') { $urlString .= '/unscheduled'; $urlParams .= '&scheduled=false'; $this->assign('unscheduled', TRUE); } elseif (CRM_Utils_Array::value(3, $newArgs) == 'archived') { $urlString .= '/archived'; $this->assign('archived', TRUE); } elseif (CRM_Utils_Array::value(3, $newArgs) == 'scheduled') { $urlString .= '/scheduled'; $urlParams .= '&scheduled=true'; } if ($this->get('sms')) { CRM_Utils_System::setTitle(ts('Find Mass SMS')); } $crmRowCount = CRM_Utils_Request::retrieve('crmRowCount', 'Integer', CRM_Core_DAO::$_nullObject); $crmPID = CRM_Utils_Request::retrieve('crmPID', 'Integer', CRM_Core_DAO::$_nullObject); if ($crmRowCount || $crmPID) { $urlParams .= '&force=1'; $urlParams .= $crmRowCount ? '&crmRowCount=' . $crmRowCount : ''; $urlParams .= $crmPID ? '&crmPID=' . $crmPID : ''; } $crmSID = CRM_Utils_Request::retrieve('crmSID', 'Integer', CRM_Core_DAO::$_nullObject); if ($crmSID) { $urlParams .= '&crmSID=' . $crmSID; } $session = CRM_Core_Session::singleton(); $url = CRM_Utils_System::url($urlString, $urlParams); $session->pushUserContext($url); // CRM-6862 -run form cotroller after // selector, since it erase $_POST $this->search(); return parent::run(); }
/** * @param $job * @param $groupId */ private static function runTestEmailJobs($job, $groupId = NULL) { $testJobParams = array(); $testJobParams['job_id'] = $job->id; if ($groupId) { $testJobParams['test_group'] = $groupId; } $isComplete = FALSE; while (!$isComplete) { $isComplete = CRM_Mailing_BAO_MailingJob::runJobs($testJobParams); } }
static function processQueue($mode = NULL) { $config =& CRM_Core_Config::singleton(); // CRM_Core_Error::debug_log_message("Beginning processQueue run: {$config->mailerJobsMax}, {$config->mailerJobSize}"); if ($mode == NULL && CRM_Core_BAO_MailSettings::defaultDomain() == "EXAMPLE.ORG") { CRM_Core_Error::fatal(ts('The <a href="%1">default mailbox</a> has not been configured. You will find <a href="%2">more info in the online user and administrator guide</a>', array(1 => CRM_Utils_System::url('civicrm/admin/mailSettings', 'reset=1'), 2 => "http://book.civicrm.org/user/advanced-configuration/email-system-configuration/"))); } // check if we are enforcing number of parallel cron jobs // CRM-8460 $gotCronLock = FALSE; if (property_exists($config, 'mailerJobsMax') && $config->mailerJobsMax && $config->mailerJobsMax > 1) { $lockArray = range(1, $config->mailerJobsMax); shuffle($lockArray); // check if we are using global locks $serverWideLock = CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::MAILING_PREFERENCES_NAME, 'civimail_server_wide_lock'); foreach ($lockArray as $lockID) { $cronLock = new CRM_Core_Lock("civimail.cronjob.{$lockID}", NULL, $serverWideLock); if ($cronLock->isAcquired()) { $gotCronLock = TRUE; break; } } // exit here since we have enuf cronjobs running if (!$gotCronLock) { CRM_Core_Error::debug_log_message('Returning early, since max number of cronjobs running'); return TRUE; } } // load bootstrap to call hooks // Split up the parent jobs into multiple child jobs $mailerJobSize = property_exists($config, 'mailerJobSize') ? $config->mailerJobSize : NULL; CRM_Mailing_BAO_MailingJob::runJobs_pre($mailerJobSize, $mode); CRM_Mailing_BAO_MailingJob::runJobs(NULL, $mode); CRM_Mailing_BAO_MailingJob::runJobs_post($mode); // lets release the global cron lock if we do have one if ($gotCronLock) { $cronLock->release(); } // CRM_Core_Error::debug_log_message('Ending processQueue run'); return TRUE; }